diff --git a/CHANGELOG.md b/CHANGELOG.md index 68967de..bf7153d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ Формат основан на [Keep a Changelog](https://keepachangelog.com/). +## [1.2.4] — 2026-08-01 + +### Changed +- Теория всех учебных дней (158) расширена до ~350–500 слов: ментальная модель, зачем нужно дальше, пример, типичная ошибка, связь с практикой +- Часы дня пересчитаны после расширения теории (`rebalance-weeks.py`) + ## [1.2.3] — 2026-08-01 ### Fixed diff --git a/README.md b/README.md index add3d3a..2af4377 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ 22 weeks 6-7h per day full-stack - v1.2.3 + v1.2.4

--- diff --git a/docs/index.html b/docs/index.html index c4b7e34..2c633ce 100644 --- a/docs/index.html +++ b/docs/index.html @@ -275,7 +275,7 @@

Помогите маршруту расти

@@ -315,7 +315,7 @@

Загрузка…

- + diff --git a/docs/search-index.json b/docs/search-index.json index 71b65e3..cf09ccc 100644 --- a/docs/search-index.json +++ b/docs/search-index.json @@ -1 +1 @@ -[{"route": "week-00", "title": "Неделя 0: Онбординг — до первого HTML", "text": "Неделя 0: Онбординг — до первого HTML Цель: подготовить инструменты, аккаунты и репозиторий learning-log до недели 1 . Время: 2–4 часа (один раз) Проект: инфраструктура обучения, не код недели Зачем отдельная неделя 0 Неделя 1 сразу про HTML и Git. Если VS Code, Git и GitHub не готовы — первый день уйдёт на установку, а не на index.html . Неделя 0 снимает трение: среда, аккаунт, репозиторий, понимание «как учиться». День 0.1: Инструменты Время (полный): ~40м теория · ~1.5ч практика · ~10м проверка Время (лайт): ~20м теория · ~45м практика Связь с проектом: стабильная среда для всех следующих недель Теория Веб-разработка начинается не с кода, а со среды : редактор, браузер с DevTools, терминал, Git. Эти инструменты останутся с вами на годы. VS Code — редактор с встроенным терминалом и Git. …", "snippet": "Неделя 0: Онбординг — до первого HTML Цель: подготовить инструменты, аккаунты и репозиторий learning-log до недели 1 . В"}, {"route": "week-01", "title": "Неделя 1: HTML — структура, семантика, формы, a11y", "text": "Неделя 1: HTML — структура, семантика, формы, a11y Цель недели: научиться создавать валидные, семантические HTML-страницы с формами и базовой доступностью — и с первого дня вести код в Git. Проект недели: Portfolio Landing — 3 страницы, форма, a11y ≥ 90. Git: репозиторий learning-log создаётся в день 1 ; первый коммит — index.html . К концу недели ≥ 7 коммитов, тег week-01-done . Литература (обязательно + по желанию) Приоритет Источник Главы / разделы ★★★ Ионетт Дакетт «HTML и CSS» гл. 1–6 ★★★ MDN Learn HTML весь трек ★★ web.dev Learn HTML семантика, формы ★★ Scott Chacon «Pro Git» гл. 1–2 — основы и коммиты ★ HTML5 Doctor (архив) семантические элементы ★ A11y Project Checklist доступность День 0 (до понедельника): Git и GitHub — подготовка Время (полный): ~35м теория · ~1.5ч практика · ~1…", "snippet": "Неделя 1: HTML — структура, семантика, формы, a11y Цель недели: научиться создавать валидные, семантические HTML-страниц"}, {"route": "week-02", "title": "Неделя 2: CSS — селекторы, box model, типографика, переменные", "text": "Неделя 2: CSS — селекторы, box model, типографика, переменные Цель недели: освоить фундамент CSS — от селекторов до типографики и кастомных свойств. Литература: Ионетт Дакетт «HTML и CSS» (гл. 10–13), web.dev Learn CSS , CSS Reference , Every Layout — паттерны без «магических» хаков Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-02/ День 1 (Mon): Подключение CSS и селекторы Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Styled Blog Post Теория CSS (Cascading Style Sheets) отделяет оформление от структуры HTML. Подключить стили можно тремя способами: inline-атрибут style (плохо для поддержки), блок <style> в <head> (допусти…", "snippet": "Неделя 2: CSS — селекторы, box model, типографика, переменные Цель недели: освоить фундамент CSS — от селекторов до типо"}, {"route": "week-03", "title": "Неделя 3: CSS — Flexbox, Grid, адаптив, анимации", "text": "Неделя 3: CSS — Flexbox, Grid, адаптив, анимации Цель недели: научиться строить современные макеты и адаптивные интерфейсы с Flexbox, Grid и анимациями. Литература: Ионетт Дакетт «HTML и CSS» (гл. 12–14), CSS Tricks: Flexbox Guide , CSS Tricks: Grid Guide , web.dev Learn CSS , Every Layout: Sidebar — готовые адаптивные паттерны Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-03/ День 1 (Mon): Flexbox — основы Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к SaaS Landing Теория Flexbox (Flexible Box Layout) решает задачу одномерного выравнивания: элементы в ряд или в колонку. Контейнер с display: flex становится flex-контейнером; прямые д…", "snippet": "Неделя 3: CSS — Flexbox, Grid, адаптив, анимации Цель недели: научиться строить современные макеты и адаптивные интерфей"}, {"route": "week-04", "title": "Неделя 4: Git Advanced, GitHub workflow, DevTools", "text": "Неделя 4: Git Advanced, GitHub workflow, DevTools Цель недели: углубить Git (ветки, merge, rebase, PR), оформить learning-log как OSS-проект, освоить DevTools. Предусловие: Git с недели 1 — репозиторий learning-log уже существует, ежедневные коммиты — привычка. Литература: Scott Chacon, Ben Straub «Pro Git» ( git-scm.com/book ), GitHub Docs , Chrome DevTools Docs , Conventional Commits , Oh Shit, Git!?! — экстренные сценарии Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-04/ День 1 (Mon): Git — ревизия основ + git log как инструмент Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к OSS Workflow Kit Теория Перед углублением в ветки стоит…", "snippet": "Неделя 4: Git Advanced, GitHub workflow, DevTools Цель недели: углубить Git (ветки, merge, rebase, PR), оформить learnin"}, {"route": "week-05", "title": "Неделя 5: JavaScript — переменные, типы, функции, массивы", "text": "Неделя 5: JavaScript — переменные, типы, функции, массивы Цель недели: заложить фундамент JavaScript — синтаксис, типы данных, функции и работа с массивами. Литература: learn.javascript.ru , Kyle Simpson «You Don't Know JS» (Scope & Closures, Types & Grammar), MDN JavaScript Guide , JavaScript.info — углублённые объяснения, Eloquent JavaScript (гл. 1–4) Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-05/ День 1 (Mon): Введение и переменные Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Console Task Manager Теория JavaScript в браузере — язык, который оживляет страницу. Браузер парсит HTML, строит DOM, затем загружает и выполняе…", "snippet": "Неделя 5: JavaScript — переменные, типы, функции, массивы Цель недели: заложить фундамент JavaScript — синтаксис, типы д"}, {"route": "week-06", "title": "Неделя 6: JavaScript — объекты, DOM, события", "text": "Неделя 6: JavaScript — объекты, DOM, события Цель недели: освоить объекты JavaScript, манипуляции DOM и обработку пользовательских событий. Литература: learn.javascript.ru: Объекты , learn.javascript.ru: DOM , MDN DOM , DOM Enlightenment (архив) — глубокое понимание DOM, web.dev Learn Forms Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-06/ День 1 (Mon): Объекты — основы Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к DOM Todo App Теория Объект в JavaScript — коллекция пар ключ–значение . Литерал { name: 'Анна', age: 25 } — самый частый способ создания. Доступ: точечная нотация user.name и скобочная user['name'] — вторая нужна для дин…", "snippet": "Неделя 6: JavaScript — объекты, DOM, события Цель недели: освоить объекты JavaScript, манипуляции DOM и обработку пользо"}, {"route": "week-07", "title": "Неделя 7: JavaScript — localStorage, Fetch, формы, модули ES", "text": "Неделя 7: JavaScript — localStorage, Fetch, формы, модули ES Цель недели: научиться сохранять данные в браузере, работать с API и организовывать код в ES-модули. Литература: learn.javascript.ru: Fetch , MDN Web Storage , MDN JavaScript modules , JSONPlaceholder Guide , web.dev Storage for the web Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-07/ День 1 (Mon): localStorage и sessionStorage Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~35м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Notes Dashboard Теория Web Storage API даёт браузеру простое key-value хранилище, привязанное к origin (протокол + домен + порт). localStorage и sessionStorage работают одинаково по API, но различаютс…", "snippet": "Неделя 7: JavaScript — localStorage, Fetch, формы, модули ES Цель недели: научиться сохранять данные в браузере, работат"}, {"route": "week-08", "title": "Неделя 8: Async JS — promises, event loop, HTTP, API patterns", "text": "Неделя 8: Async JS — promises, event loop, HTTP, API patterns Цель недели: глубоко понять асинхронность в JavaScript, Promises, Event Loop и паттерны работы с API. Литература: Kyle Simpson «You Don't Know JS: Async & Performance», learn.javascript.ru: Промисы , MDN Event Loop , JavaScript.info: Event loop , Philip Roberts: What the heck is the event loop? Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-08/ День 1 (Mon): Асинхронность и Event Loop Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Movie Catalog Теория JavaScript однопоточен: в каждый момент времени выполняется только один фрагмент кода на main thread. Синхронные операци…", "snippet": "Неделя 8: Async JS — promises, event loop, HTTP, API patterns Цель недели: глубоко понять асинхронность в JavaScript, Pr"}, {"route": "week-09", "title": "Неделя 9: JS advanced — closures, prototypes, classes, patterns", "text": "Неделя 9: JS advanced — closures, prototypes, classes, patterns Цель недели: углубить понимание JavaScript — замыкания, прототипы, классы и практические паттерны проектирования. Литература: Kyle Simpson «YDKJS: Scope & Closures», «YDKJS: this & Object Prototypes», learn.javascript.ru: Прототипы , patterns.dev , MDN: Closures , javascript.info: Продвинутая работа с функциями Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-09/ День 1 (Mon): Scope и замыкания Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Library System Теория Область видимости (scope) определяет, где переменная доступна для чтения и записи. В JavaScript действует…", "snippet": "Неделя 9: JS advanced — closures, prototypes, classes, patterns Цель недели: углубить понимание JavaScript — замыкания, "}, {"route": "week-10", "title": "Неделя 10: TypeScript — типы, interfaces, generics basics, TS+React setup", "text": "Неделя 10: TypeScript — типы, interfaces, generics basics, TS+React setup Цель недели: освоить основы TypeScript и подготовить проект к React с типизированной кодовой базой. Литература: TypeScript Handbook , learn.javascript.ru: Типы , React TypeScript Cheatsheet , Total TypeScript — Beginners , TSConfig Reference Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-10/ День 1 (Mon): Введение в TypeScript Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Typed API Client Теория TypeScript — это надмножество JavaScript со статической системой типов. Код пишется в .ts (или .tsx для JSX), компилируется компилятором tsc в обычный JavaScript, котор…", "snippet": "Неделя 10: TypeScript — типы, interfaces, generics basics, TS+React setup Цель недели: освоить основы TypeScript и подго"}, {"route": "week-11", "title": "Неделя 11: React — компоненты, JSX, props, Vite, первые компоненты", "text": "Неделя 11: React — компоненты, JSX, props, Vite, первые компоненты Цель недели: создать первое React-приложение на Vite, освоить компоненты, JSX, props и базовые паттерны. Литература: react.dev Learn , React TypeScript Cheatsheet , Vite Guide , Thinking in React , React — Quick Start Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-11/ День 1 (Mon): Введение в React и JSX Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к React Todo Теория React — библиотека для построения пользовательских интерфейсов на основе компонентов. Компонент — это JavaScript-функция (или класс), которая принимает props и возвращает описание UI. React берёт это опис…", "snippet": "Неделя 11: React — компоненты, JSX, props, Vite, первые компоненты Цель недели: создать первое React-приложение на Vite,"}, {"route": "week-12", "title": "Неделя 12: React — state, эффекты, формы", "text": "Неделя 12: React — state, эффекты, формы Цель недели: научиться управлять состоянием компонентов, побочными эффектами и формами в React. Литература: react.dev — Learn , React — State , React — Effects , You Might Not Need an Effect , React — Forms Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-12/ День 78 (Пн): useState — память компонента Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к React Todo Pro Теория useState — фундаментальный hook React, дающий функциональному компоненту локальное состояние. При первом рендере React создаёт ячейку state; при последующих — возвращает сохранённое значение. setState не меняет переменную мгновенно…", "snippet": "Неделя 12: React — state, эффекты, формы Цель недели: научиться управлять состоянием компонентов, побочными эффектами и "}, {"route": "week-13", "title": "Неделя 13: React Router, хуки, Context", "text": "Неделя 13: React Router, хуки, Context Цель недели: построить многостраничное SPA с переиспользуемой логикой и глобальным состоянием. Литература: React Router , react.dev — Context , react.dev — Reusing Logic , React Router Tutorial , useDebounce patterns Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-13/ День 85 (Пн): React Router — основы Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Portfolio SPA Теория Одностраничное приложение (SPA) живёт в одной HTML-странице, но пользователь ожидает поведение «настоящего сайта»: разные URL, кнопка «Назад» в браузере, закладки на конкретные экраны. React Router решает эту задачу на клиенте: п…", "snippet": "Неделя 13: React Router, хуки, Context Цель недели: построить многостраничное SPA с переиспользуемой логикой и глобальны"}, {"route": "week-14", "title": "Неделя 14: Frontend Capstone — React Dashboard", "text": "Неделя 14: Frontend Capstone — React Dashboard Цель недели: собрать полноценное SPA-приложение, объединяющее все навыки React-фронтенда. Литература: react.dev , React Router , OpenWeatherMap API , Vite Env Variables , web.dev — Web Vitals Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-14/ День 92 (Пн): Архитектура и скелет проекта Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к React Dashboard Теория Frontend capstone начинается с архитектуры, а не с кода. Прежде чем писать компоненты, зафиксируй страницы ( / , /tasks , /weather , /settings ), источники данных (localStorage, Context, внешний API) и границы ответственности модулей. Хоро…", "snippet": "Неделя 14: Frontend Capstone — React Dashboard Цель недели: собрать полноценное SPA-приложение, объединяющее все навыки "}, {"route": "week-15", "title": "Неделя 15: Python — основы", "text": "Неделя 15: Python — основы Цель недели: освоить синтаксис Python, структуры данных, функции и изолированное окружение. Литература: Python Tutorial , Real Python , «Python. Ускоренный курс» (Теллез), PEP 8 , Python venv Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-15/ День 99 (Пн): Установка, синтаксис, venv Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к CLI Expense Tracker Теория Python — первый шаг в backend после фронтенда. Установка с python.org (или py launcher на Windows) и проверка python --version — база. Главная привычка с первого дня: виртуальное окружение python -m venv .venv изолирует зависимости проекта от системного Pyt…", "snippet": "Неделя 15: Python — основы Цель недели: освоить синтаксис Python, структуры данных, функции и изолированное окружение. Л"}, {"route": "week-16", "title": "Неделя 16: Python — ООП, алгоритмы, файлы", "text": "Неделя 16: Python — ООП, алгоритмы, файлы Цель недели: освоить объектно-ориентированный Python, оценку сложности и работу с файловой системой. Литература: Python OOP , Real Python — pathlib , Big-O Cheat Sheet Проект недели: CLI Task Manager (SQLite) — классы Task , TaskRepository , CRUD через sqlite3 , теги many-to-many. Git: папка learning-log/week-16/ , минимум 1 осмысленный коммит в день; к концу недели тег week-16-done . День 106 (Пн): Классы и объекты Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к CLI Task Manager Теория Объектно-ориентированное программирование в Python объединяет данные и поведение в одной сущности — классе. class BankAccount: с методом __init__(self, ...) инициал…", "snippet": "Неделя 16: Python — ООП, алгоритмы, файлы Цель недели: освоить объектно-ориентированный Python, оценку сложности и работ"}, {"route": "week-17", "title": "Неделя 17: SQL, PostgreSQL, индексы", "text": "Неделя 17: SQL, PostgreSQL, индексы Цель недели: освоить реляционные БД, SQL-запросы, PostgreSQL и оптимизацию через индексы. Литература: SQLBolt , PostgreSQL Tutorial , Use The Index, Luke Проект недели: Library Database — PostgreSQL-схема библиотеки, 15+ запросов, индексы, EXPLAIN. Git: папка learning-log/week-17/ , SQL-скрипты в schema.sql , seed.sql , queries.sql ; тег week-17-done . День 113 (Пн): SQL основы — SELECT, фильтрация, сортировка Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Library Database Теория SQL — декларативный язык: ты описываешь, какие данные нужны, а СУБД решает, как их достать. Базовый pipeline: SELECT колонки FROM таблицы WHERE условие ORDER BY сортировка LIM…", "snippet": "Неделя 17: SQL, PostgreSQL, индексы Цель недели: освоить реляционные БД, SQL-запросы, PostgreSQL и оптимизацию через инд"}, {"route": "week-18", "title": "Неделя 18: SQLAlchemy ORM + FastAPI", "text": "Неделя 18: SQLAlchemy ORM + FastAPI Цель недели: построить типобезопасный REST API на Python с ORM и автодокументацией. Литература: SQLAlchemy 2.0 ORM , FastAPI Tutorial , Pydantic Проект недели: Library REST API — FastAPI + SQLAlchemy, full CRUD, pytest ≥ 8, Swagger. Git: папка learning-log/week-18/ , feature-ветки по роутерам; тег week-18-done . День 120 (Пн): SQLAlchemy — модели и сессии Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Library REST API Теория SQLAlchemy 2.0 — современный ORM для Python. DeclarativeBase, Mapped[type] и mapped_column() задают модели типобезопасно. Engine — подключение к PostgreSQL; SessionLocal — фабрика сессий. Сессия — unit of work: session.add(obj) , c…", "snippet": "Неделя 18: SQLAlchemy ORM + FastAPI Цель недели: построить типобезопасный REST API на Python с ORM и автодокументацией. "}, {"route": "week-19", "title": "Неделя 19: Node.js + Express REST API", "text": "Неделя 19: Node.js + Express REST API Цель недели: построить REST API на JavaScript в среде Node.js с Express и PostgreSQL. Литература: Node.js Docs , Express Guide , node-postgres Проект недели: Express Notes API — layered Express API, Zod, PostgreSQL, Postman collection. Git: папка learning-log/week-19/ , ветки feature/routes , feature/pg ; тег week-19-done . День 127 (Пн): Node.js — среда и модули Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Express Notes API Теория Node.js — среда выполнения JavaScript вне браузера. Нет DOM и window , зато есть process , встроенные модули и npm-экосистема. Backend на Node разделяет язык с фронтендом — один TypeScript/JavaScript на обе стороны, но r…", "snippet": "Неделя 19: Node.js + Express REST API Цель недели: построить REST API на JavaScript в среде Node.js с Express и PostgreS"}, {"route": "week-20", "title": "Неделя 20: Auth, безопасность, тестирование", "text": "Неделя 20: Auth, безопасность, тестирование Цель недели: реализовать JWT-аутентификацию, изучить OWASP и написать базовые тесты (Vitest + pytest). Литература: JWT.io , OWASP Top 10 , Vitest , pytest Проект недели: Secure Notes — JWT auth, bcrypt, rate limit, React client, pytest + Vitest. Git: папка learning-log/week-20/ , отдельные коммиты backend/frontend; тег week-20-done . День 134 (Пн): Аутентификация и хеширование паролей Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Secure Notes Теория Authentication отвечает на вопрос «кто ты?» — проверка личности (логин/пароль). Authorization — «что тебе можно?» — права на ресурсы. Не путай: успешный login не означает доступ ко всем endpoints. …", "snippet": "Неделя 20: Auth, безопасность, тестирование Цель недели: реализовать JWT-аутентификацию, изучить OWASP и написать базовы"}, {"route": "week-21", "title": "Неделя 21: Full-Stack интеграция и Docker", "text": "Неделя 21: Full-Stack интеграция и Docker Цель недели: связать React-фронтенд с бэкендом и упаковать всё в Docker Compose. Литература: Docker Docs , docker-compose , Vite Env Проект недели: Task Manager Docker — React + API + PostgreSQL в docker-compose , healthchecks, seed. Git: папка learning-log/week-21/ , monorepo или два репо в одной папке; тег week-21-done . День 141 (Пн): Связка Frontend + Backend Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Task Manager Docker Теория Full-stack начинается там, где фронтенд и бэкенд встречаются в браузере. Same-origin policy: localhost:5173 (Vite) и localhost:3000 (API) — разные origins. Браузер блокирует cross-origin fetch без заголовков CORS о…", "snippet": "Неделя 21: Full-Stack интеграция и Docker Цель недели: связать React-фронтенд с бэкендом и упаковать всё в Docker Compos"}, {"route": "week-22", "title": "Неделя 22: DevHub Capstone — финальный full-stack проект", "text": "Неделя 22: DevHub Capstone — финальный full-stack проект Цель недели: собрать, протестировать и задеплоить DevHub — единый capstone, объединяющий весь стек 22 недель обучения. Литература: docs/projects.md — DevHub Capstone , Vercel Docs , Render Docs , GitHub Actions Проект недели: DevHub Capstone — персональная платформа разработчика: дашборд + заметки + задачи + GitHub API. Git: папка learning-log/week-22-capstone/ , feature-ветки по дням 149–153; тег week-22-done + обновление GitHub Profile README. Не начинайте с нуля в последний день. Планируйте в день 148, кодите 149–153, деплой и портфолио — в день 154. Полная спецификация MVP, стека и критериев сдачи — в каталоге проектов . День 148 (Пн): Планирование DevHub Capstone Время (полный): ~1ч теория · ~3.5ч практика · ~15м Git · ~45м ревь…", "snippet": "Неделя 22: DevHub Capstone — финальный full-stack проект Цель недели: собрать, протестировать и задеплоить DevHub — един"}, {"route": "intro", "title": "Введение", "text": "Введение Добро пожаловать в web-roadmap — 22-недельный путь к junior full-stack разработчику. Главная цель Перестать быть «вайбкодером» и стать инженером, который понимает, почему код работает , и может переписать его без ИИ. Главный враг — иллюзия компетентности. Туториал посмотрел — кажется, всё ясно. Мы ломаем эту иллюзию ежедневной практикой . Принцип прогрессии Наглядное → Логика → Абстракции → Системы HTML/CSS → JS → React/TS → Full-Stack + DevOps Не перепрыгивайте: слабый фундамент в HTML/JS превратит React и бэкенд в мучение. Фазы маршрута Фазы Недели Фокус Вёрстка 1–3 HTML, CSS, адаптив Git & workflow 1, 4 Git с дня 1; нед. 4 — advanced, PR, OSS Язык браузера 5–10 JS, async, TypeScript Фронтенд 11–14 React, SPA-проект Python & данные 15–18 Python, SQL, FastAPI JS-бэкенд 19…", "snippet": "Введение Добро пожаловать в web-roadmap — 22-недельный путь к junior full-stack разработчику. Главная цель Перестать быт"}, {"route": "start", "title": "Начало работы", "text": "Начало работы Сколько времени Параметр Значение Длительность 22 недели (154 дня) Нагрузка ~5–7 ч/день (полный) или ~3–4 ч (лайт) Проекты 22 недельных + 1 capstone (неделя 22) Итог Junior full-stack portfolio + понимание стека Если у вас меньше времени — растяните недели; не пропускайте проекты недели . Каталог: projects.md . Git с первого дня (обязательно) До недели 1, день 0 вы создаёте публичный репозиторий learning-log на GitHub. В день 1 недели 1 вы коммитите свой первый index.html . Это не «потом разберусь» — Git часть учебного процесса с первой строки HTML. Быстрый старт Git # 1. GitHub → New repository → learning-log # Public, БЕЗ README / .gitignore / license (пустой репозиторий под вашим аккаунтом) git clone https://github.com/<ваш-логин>/learning-log.git cd learning-log # 2…", "snippet": "Начало работы Сколько времени Параметр Значение Длительность 22 недели (154 дня) Нагрузка ~5–7 ч/день (полный) или ~3–4 "}, {"route": "projects", "title": "Каталог проектов: 22 + Capstone", "text": "Каталог проектов: 22 + Capstone Каждая неделя заканчивается работающим проектом в вашем репозитории learning-log . Недели 1–21 накапливают навыки; неделя 22 — единый крупномасштабный capstone со всем стеком. Правило: проект недели = отдельная папка week-NN/ (или week-NN-project-name/ ), тег week-NN-done , README внутри папки. Обзор Нед. Проект Стек Папка 01 Portfolio Landing HTML, a11y, формы week-01/ 02 Styled Blog Post CSS, design tokens week-02/ 03 SaaS Landing Flexbox, Grid, адаптив week-03/ 04 OSS Workflow Kit Git, PR, GitHub Pages week-04/ 05 Console Task Manager Vanilla JS, массивы week-05/ 06 DOM Todo App DOM, события week-06/ 07 Notes Dashboard ES modules, Fetch, storage week-07/ 08 Movie Catalog async/await, REST API week-08/ 09 Library System OOP, паттерны, Observer week-09/ 10 …", "snippet": "Каталог проектов: 22 + Capstone Каждая неделя заканчивается работающим проектом в вашем репозитории learning-log . Недел"}, {"route": "cheatsheet-html", "title": "HTML & CSS — шпаргалка", "text": "HTML & CSS — шпаргалка После недель 1–3. Полный маршрут HTML семантика header → nav → main → section/article → aside → footer Один h1 на страницу, иерархия без пропусков label[for] ↔ input[id] img + alt ; декоративное → alt=\"\" Формы: required , pattern , fieldset / legend Box model content → padding → border → margin *, *::before, *::after { box-sizing: border-box; } Flexbox .container { display: flex; gap: 1rem; justify-content: center; align-items: center; } .item { flex: 1; } /* grow */ Grid .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1rem; } Адаптив /* mobile-first */ .hero { font-size: clamp(1.5rem, 4vw, 2.5rem); } @media (min-width: 768px) { ... } Design tokens :root { --color-bg: #050508; --space-md: 1rem; --radius: 12px; }", "snippet": "HTML & CSS — шпаргалка После недель 1–3. Полный маршрут HTML семантика header → nav → main → section/article → aside"}, {"route": "cheatsheet-js", "title": "JavaScript & TypeScript — шпаргалка", "text": "JavaScript & TypeScript — шпаргалка После недель 5–10. Типы и сравнение Примитивы: string , number , boolean , null , undefined , bigint , symbol Всегда === , не == const по умолчанию; let если переприсвоение Массивы arr.map(x => x * 2) arr.filter(x => x.done) arr.find(x => x.id === id) arr.reduce((sum, x) => sum + x, 0) // slice — копия; splice — мутирует Async async function load() { const res = await fetch(url); if (!res.ok) throw new Error(res.status); return res.json(); } Event Loop (упрощённо) sync code → microtasks (Promise) → macrotasks (setTimeout) → render Модули // utils.js export function fmt(d) { ... } // app.js import { fmt } from './utils.js'; TypeScript interface User { id: number; name: string } type Status = 'active' | 'done'; function wrap<T>(x: T):…", "snippet": "JavaScript & TypeScript — шпаргалка После недель 5–10. Типы и сравнение Примитивы: string , number , boolean , null "}, {"route": "cheatsheet-react", "title": "React — шпаргалка", "text": "React — шпаргалка После недель 11–14. Компонент type Props = { title: string; onSave: () => void }; export function Card({ title, onSave }: Props) { return <article><h2>{title}</h2><button onClick={onSave}>Save</button></article>; } State & effects const [count, setCount] = useState(0); useEffect(() => { document.title = `Tasks: ${count}`; return () => { /* cleanup */ }; }, [count]); Формы (controlled) const [text, setText] = useState(''); <input value={text} onChange={e => setText(e.target.value)} /> Router <Routes> <Route path="/" element={<Home />} /> <Route path="/tasks/:id" element={<TaskDetail />} /> </Routes> Context const ThemeCtx = createContext<'light'|'dark'>('…", "snippet": "React — шпаргалка После недель 11–14. Компонент type Props = { title: string; onSave: () => void }; export function C"}, {"route": "cheatsheet-sql", "title": "SQL & PostgreSQL — шпаргалка", "text": "SQL & PostgreSQL — шпаргалка После недели 17. CRUD SELECT id, title FROM tasks WHERE user_id = $1 ORDER BY created_at DESC; INSERT INTO tasks (title, user_id) VALUES ($1, $2) RETURNING *; UPDATE tasks SET done = true WHERE id = $1 AND user_id = $2; DELETE FROM tasks WHERE id = $1 AND user_id = $2; JOIN SELECT b.title, a.name FROM books b JOIN authors a ON b.author_id = a.id; Индексы CREATE INDEX idx_tasks_user ON tasks(user_id); EXPLAIN ANALYZE SELECT ...; Нормализация (кратко) 1NF: атомарные значения 2NF: нет частичных зависимостей от составного ключа 3NF: нет транзитивных зависимостей Транзакции BEGIN; -- ops COMMIT; -- или ROLLBACK; Миграции Версионируй схему: schema.sql , migrations/001_*.sql , seed отдельно.", "snippet": "SQL & PostgreSQL — шпаргалка После недели 17. CRUD SELECT id, title FROM tasks WHERE user_id = $1 ORDER BY created_a"}, {"route": "cheatsheet-backend", "title": "FastAPI & Backend — шпаргалка", "text": "FastAPI & Backend — шпаргалка После недель 18–21. FastAPI минимум from fastapi import FastAPI, Depends, HTTPException app = FastAPI() @app.get("/api/v1/tasks") def list_tasks(db = Depends(get_db)): return db.query(Task).all() Pydantic class TaskCreate(BaseModel): title: str = Field(min_length=1, max_length=200) JWT flow register → hash password (bcrypt) login → issue access token (short) + optional refresh protected route → Depends(get_current_user) Express слои routes → controllers → services → db middleware: cors, helmet, rateLimit, errorHandler Docker Compose services: db: { image: postgres:16, environment: {...}, volumes: [...] } api: { build: ./backend, depends_on: [db], ports: ["8000:8000"] } web: { build: ./frontend, ports: ["5173:80"] } Security ch…", "snippet": "FastAPI & Backend — шпаргалка После недель 18–21. FastAPI минимум from fastapi import FastAPI, Depends, HTTPExceptio"}] \ No newline at end of file +[{"route": "week-00", "title": "Неделя 0: Онбординг — до первого HTML", "text": "Неделя 0: Онбординг — до первого HTML Цель: подготовить инструменты, аккаунты и репозиторий learning-log до недели 1 . Время: 2–4 часа (один раз) Проект: инфраструктура обучения, не код недели Зачем отдельная неделя 0 Неделя 1 сразу про HTML и Git. Если VS Code, Git и GitHub не готовы — первый день уйдёт на установку, а не на index.html . Неделя 0 снимает трение: среда, аккаунт, репозиторий, понимание «как учиться». День 0.1: Инструменты Время (полный): ~40м теория · ~1.5ч практика · ~10м проверка Время (лайт): ~20м теория · ~45м практика Связь с проектом: стабильная среда для всех следующих недель Теория Веб-разработка начинается не с кода, а со среды : редактор, браузер с DevTools, терминал, Git. Эти инструменты останутся с вами на годы, поэтому час, потраченный сегодня на настройку, оку…", "snippet": "Неделя 0: Онбординг — до первого HTML Цель: подготовить инструменты, аккаунты и репозиторий learning-log до недели 1 . В"}, {"route": "week-01", "title": "Неделя 1: HTML — структура, семантика, формы, a11y", "text": "Неделя 1: HTML — структура, семантика, формы, a11y Цель недели: научиться создавать валидные, семантические HTML-страницы с формами и базовой доступностью — и с первого дня вести код в Git. Проект недели: Portfolio Landing — 3 страницы, форма, a11y ≥ 90. Git: репозиторий learning-log создаётся в день 1 ; первый коммит — index.html . К концу недели ≥ 7 коммитов, тег week-01-done . Литература (обязательно + по желанию) Приоритет Источник Главы / разделы ★★★ Ионетт Дакетт «HTML и CSS» гл. 1–6 ★★★ MDN Learn HTML весь трек ★★ web.dev Learn HTML семантика, формы ★★ Scott Chacon «Pro Git» гл. 1–2 — основы и коммиты ★ HTML5 Doctor (архив) семантические элементы ★ A11y Project Checklist доступность День 0 (до понедельника): Git и GitHub — подготовка Время (полный): ~55м теория · ~1.5ч практика · ~1…", "snippet": "Неделя 1: HTML — структура, семантика, формы, a11y Цель недели: научиться создавать валидные, семантические HTML-страниц"}, {"route": "week-02", "title": "Неделя 2: CSS — селекторы, box model, типографика, переменные", "text": "Неделя 2: CSS — селекторы, box model, типографика, переменные Цель недели: освоить фундамент CSS — от селекторов до типографики и кастомных свойств. Литература: Ионетт Дакетт «HTML и CSS» (гл. 10–13), web.dev Learn CSS , CSS Reference , Every Layout — паттерны без «магических» хаков Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-02/ День 1 (Mon): Подключение CSS и селекторы Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Styled Blog Post Теория CSS (Cascading Style Sheets) отделяет оформление от структуры HTML. Подключить стили можно тремя способами: inline-атрибут style (плохо для поддержки), блок <style> в <head> (допусти…", "snippet": "Неделя 2: CSS — селекторы, box model, типографика, переменные Цель недели: освоить фундамент CSS — от селекторов до типо"}, {"route": "week-03", "title": "Неделя 3: CSS — Flexbox, Grid, адаптив, анимации", "text": "Неделя 3: CSS — Flexbox, Grid, адаптив, анимации Цель недели: научиться строить современные макеты и адаптивные интерфейсы с Flexbox, Grid и анимациями. Литература: Ионетт Дакетт «HTML и CSS» (гл. 12–14), CSS Tricks: Flexbox Guide , CSS Tricks: Grid Guide , web.dev Learn CSS , Every Layout: Sidebar — готовые адаптивные паттерны Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-03/ День 1 (Mon): Flexbox — основы Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к SaaS Landing Теория Flexbox (Flexible Box Layout) решает задачу одномерного выравнивания: элементы в ряд или в колонку. Контейнер с display: flex становится flex-контейнером; прямые д…", "snippet": "Неделя 3: CSS — Flexbox, Grid, адаптив, анимации Цель недели: научиться строить современные макеты и адаптивные интерфей"}, {"route": "week-04", "title": "Неделя 4: Git Advanced, GitHub workflow, DevTools", "text": "Неделя 4: Git Advanced, GitHub workflow, DevTools Цель недели: углубить Git (ветки, merge, rebase, PR), оформить learning-log как OSS-проект, освоить DevTools. Предусловие: Git с недели 1 — репозиторий learning-log уже существует, ежедневные коммиты — привычка. Литература: Scott Chacon, Ben Straub «Pro Git» ( git-scm.com/book ), GitHub Docs , Chrome DevTools Docs , Conventional Commits , Oh Shit, Git!?! — экстренные сценарии Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-04/ День 1 (Mon): Git — ревизия основ + git log как инструмент Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к OSS Workflow Kit Теория Перед углублением в ветки стоит …", "snippet": "Неделя 4: Git Advanced, GitHub workflow, DevTools Цель недели: углубить Git (ветки, merge, rebase, PR), оформить learnin"}, {"route": "week-05", "title": "Неделя 5: JavaScript — переменные, типы, функции, массивы", "text": "Неделя 5: JavaScript — переменные, типы, функции, массивы Цель недели: заложить фундамент JavaScript — синтаксис, типы данных, функции и работа с массивами. Литература: learn.javascript.ru , Kyle Simpson «You Don't Know JS» (Scope & Closures, Types & Grammar), MDN JavaScript Guide , JavaScript.info — углублённые объяснения, Eloquent JavaScript (гл. 1–4) Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-05/ День 1 (Mon): Введение и переменные Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Console Task Manager Теория JavaScript в браузере — язык, который оживляет страницу. Браузер парсит HTML, строит DOM, затем загружает и выполняе…", "snippet": "Неделя 5: JavaScript — переменные, типы, функции, массивы Цель недели: заложить фундамент JavaScript — синтаксис, типы д"}, {"route": "week-06", "title": "Неделя 6: JavaScript — объекты, DOM, события", "text": "Неделя 6: JavaScript — объекты, DOM, события Цель недели: освоить объекты JavaScript, манипуляции DOM и обработку пользовательских событий. Литература: learn.javascript.ru: Объекты , learn.javascript.ru: DOM , MDN DOM , DOM Enlightenment (архив) — глубокое понимание DOM, web.dev Learn Forms Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-06/ День 1 (Mon): Объекты — основы Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к DOM Todo App Теория Объект в JavaScript — коллекция пар ключ–значение . Литерал { name: 'Анна', age: 25 } — самый частый способ создания. Доступ: точечная нотация user.name и скобочная user['name'] — вторая нужна для дина…", "snippet": "Неделя 6: JavaScript — объекты, DOM, события Цель недели: освоить объекты JavaScript, манипуляции DOM и обработку пользо"}, {"route": "week-07", "title": "Неделя 7: JavaScript — localStorage, Fetch, формы, модули ES", "text": "Неделя 7: JavaScript — localStorage, Fetch, формы, модули ES Цель недели: научиться сохранять данные в браузере, работать с API и организовывать код в ES-модули. Литература: learn.javascript.ru: Fetch , MDN Web Storage , MDN JavaScript modules , JSONPlaceholder Guide , web.dev Storage for the web Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-07/ День 1 (Mon): localStorage и sessionStorage Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Notes Dashboard Теория Web Storage API даёт браузеру простое key-value хранилище, привязанное к origin (протокол + домен + порт). localStorage и sessionStorage работают одинаково по API, но различаются …", "snippet": "Неделя 7: JavaScript — localStorage, Fetch, формы, модули ES Цель недели: научиться сохранять данные в браузере, работат"}, {"route": "week-08", "title": "Неделя 8: Async JS — promises, event loop, HTTP, API patterns", "text": "Неделя 8: Async JS — promises, event loop, HTTP, API patterns Цель недели: глубоко понять асинхронность в JavaScript, Promises, Event Loop и паттерны работы с API. Литература: Kyle Simpson «You Don't Know JS: Async & Performance», learn.javascript.ru: Промисы , MDN Event Loop , JavaScript.info: Event loop , Philip Roberts: What the heck is the event loop? Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-08/ День 1 (Mon): Асинхронность и Event Loop Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Movie Catalog Теория JavaScript однопоточен: в каждый момент времени выполняется только один фрагмент кода на main thread. Синхронные операци…", "snippet": "Неделя 8: Async JS — promises, event loop, HTTP, API patterns Цель недели: глубоко понять асинхронность в JavaScript, Pr"}, {"route": "week-09", "title": "Неделя 9: JS advanced — closures, prototypes, classes, patterns", "text": "Неделя 9: JS advanced — closures, prototypes, classes, patterns Цель недели: углубить понимание JavaScript — замыкания, прототипы, классы и практические паттерны проектирования. Литература: Kyle Simpson «YDKJS: Scope & Closures», «YDKJS: this & Object Prototypes», learn.javascript.ru: Прототипы , patterns.dev , MDN: Closures , javascript.info: Продвинутая работа с функциями Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-09/ День 1 (Mon): Scope и замыкания Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Library System Теория Область видимости (scope) определяет, где переменная доступна для чтения и записи. В JavaScript действует…", "snippet": "Неделя 9: JS advanced — closures, prototypes, classes, patterns Цель недели: углубить понимание JavaScript — замыкания, "}, {"route": "week-10", "title": "Неделя 10: TypeScript — типы, interfaces, generics basics, TS+React setup", "text": "Неделя 10: TypeScript — типы, interfaces, generics basics, TS+React setup Цель недели: освоить основы TypeScript и подготовить проект к React с типизированной кодовой базой. Литература: TypeScript Handbook , learn.javascript.ru: Типы , React TypeScript Cheatsheet , Total TypeScript — Beginners , TSConfig Reference Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-10/ День 1 (Mon): Введение в TypeScript Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Typed API Client Теория TypeScript — это надмножество JavaScript со статической системой типов. Код пишется в .ts (или .tsx для JSX), компилируется компилятором tsc в обычный JavaScript, котор…", "snippet": "Неделя 10: TypeScript — типы, interfaces, generics basics, TS+React setup Цель недели: освоить основы TypeScript и подго"}, {"route": "week-11", "title": "Неделя 11: React — компоненты, JSX, props, Vite, первые компоненты", "text": "Неделя 11: React — компоненты, JSX, props, Vite, первые компоненты Цель недели: создать первое React-приложение на Vite, освоить компоненты, JSX, props и базовые паттерны. Литература: react.dev Learn , React TypeScript Cheatsheet , Vite Guide , Thinking in React , React — Quick Start Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-11/ День 1 (Mon): Введение в React и JSX Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к React Todo Теория React — библиотека для построения пользовательских интерфейсов на основе компонентов. Компонент — это JavaScript-функция (или класс), которая принимает props и возвращает описание UI. React берёт это опис…", "snippet": "Неделя 11: React — компоненты, JSX, props, Vite, первые компоненты Цель недели: создать первое React-приложение на Vite,"}, {"route": "week-12", "title": "Неделя 12: React — state, эффекты, формы", "text": "Неделя 12: React — state, эффекты, формы Цель недели: научиться управлять состоянием компонентов, побочными эффектами и формами в React. Литература: react.dev — Learn , React — State , React — Effects , You Might Not Need an Effect , React — Forms Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-12/ День 78 (Пн): useState — память компонента Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к React Todo Pro Теория useState — фундаментальный hook React, дающий функциональному компоненту локальное состояние. При первом рендере React создаёт ячейку state; при последующих — возвращает сохранённое значение. setState не меняет переменную мгновенно…", "snippet": "Неделя 12: React — state, эффекты, формы Цель недели: научиться управлять состоянием компонентов, побочными эффектами и "}, {"route": "week-13", "title": "Неделя 13: React Router, хуки, Context", "text": "Неделя 13: React Router, хуки, Context Цель недели: построить многостраничное SPA с переиспользуемой логикой и глобальным состоянием. Литература: React Router , react.dev — Context , react.dev — Reusing Logic , React Router Tutorial , useDebounce patterns Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-13/ День 85 (Пн): React Router — основы Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Portfolio SPA Теория Одностраничное приложение (SPA) живёт в одной HTML-странице, но пользователь ожидает поведение «настоящего сайта»: разные URL, кнопка «Назад» в браузере, закладки на конкретные экраны. React Router решает эту задачу на клиенте: при…", "snippet": "Неделя 13: React Router, хуки, Context Цель недели: построить многостраничное SPA с переиспользуемой логикой и глобальны"}, {"route": "week-14", "title": "Неделя 14: Frontend Capstone — React Dashboard", "text": "Неделя 14: Frontend Capstone — React Dashboard Цель недели: собрать полноценное SPA-приложение, объединяющее все навыки React-фронтенда. Литература: react.dev , React Router , OpenWeatherMap API , Vite Env Variables , web.dev — Web Vitals Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-14/ День 92 (Пн): Архитектура и скелет проекта Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к React Dashboard Теория Frontend capstone начинается с архитектуры, а не с кода. Прежде чем писать компоненты, зафиксируй страницы ( / , /tasks , /weather , /settings ), источники данных (localStorage, Context, внешний API) и границы ответственности модулей. Хоро…", "snippet": "Неделя 14: Frontend Capstone — React Dashboard Цель недели: собрать полноценное SPA-приложение, объединяющее все навыки "}, {"route": "week-15", "title": "Неделя 15: Python — основы", "text": "Неделя 15: Python — основы Цель недели: освоить синтаксис Python, структуры данных, функции и изолированное окружение. Литература: Python Tutorial , Real Python , «Python. Ускоренный курс» (Теллез), PEP 8 , Python venv Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-15/ День 99 (Пн): Установка, синтаксис, venv Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к CLI Expense Tracker Теория Python — первый шаг в backend после фронтенда. Установка с python.org (или py launcher на Windows) и проверка python --version — база. Главная привычка с первого дня: виртуальное окружение python -m venv .venv изолирует зависимости проекта от системного Pyt…", "snippet": "Неделя 15: Python — основы Цель недели: освоить синтаксис Python, структуры данных, функции и изолированное окружение. Л"}, {"route": "week-16", "title": "Неделя 16: Python — ООП, алгоритмы, файлы", "text": "Неделя 16: Python — ООП, алгоритмы, файлы Цель недели: освоить объектно-ориентированный Python, оценку сложности и работу с файловой системой. Литература: Python OOP , Real Python — pathlib , Big-O Cheat Sheet Проект недели: CLI Task Manager (SQLite) — классы Task , TaskRepository , CRUD через sqlite3 , теги many-to-many. Git: папка learning-log/week-16/ , минимум 1 осмысленный коммит в день; к концу недели тег week-16-done . День 106 (Пн): Классы и объекты Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к CLI Task Manager Теория Объектно-ориентированное программирование в Python объединяет данные и поведение в одной сущности — классе. class BankAccount: с методом __init__(self, ...) инициал…", "snippet": "Неделя 16: Python — ООП, алгоритмы, файлы Цель недели: освоить объектно-ориентированный Python, оценку сложности и работ"}, {"route": "week-17", "title": "Неделя 17: SQL, PostgreSQL, индексы", "text": "Неделя 17: SQL, PostgreSQL, индексы Цель недели: освоить реляционные БД, SQL-запросы, PostgreSQL и оптимизацию через индексы. Литература: SQLBolt , PostgreSQL Tutorial , Use The Index, Luke Проект недели: Library Database — PostgreSQL-схема библиотеки, 15+ запросов, индексы, EXPLAIN. Git: папка learning-log/week-17/ , SQL-скрипты в schema.sql , seed.sql , queries.sql ; тег week-17-done . День 113 (Пн): SQL основы — SELECT, фильтрация, сортировка Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Library Database Теория SQL — декларативный язык: ты описываешь, какие данные нужны, а СУБД решает, как их достать. Базовый pipeline: SELECT колонки FROM таблицы WHERE условие ORDER BY сортировка LIMI…", "snippet": "Неделя 17: SQL, PostgreSQL, индексы Цель недели: освоить реляционные БД, SQL-запросы, PostgreSQL и оптимизацию через инд"}, {"route": "week-18", "title": "Неделя 18: SQLAlchemy ORM + FastAPI", "text": "Неделя 18: SQLAlchemy ORM + FastAPI Цель недели: построить типобезопасный REST API на Python с ORM и автодокументацией. Литература: SQLAlchemy 2.0 ORM , FastAPI Tutorial , Pydantic Проект недели: Library REST API — FastAPI + SQLAlchemy, full CRUD, pytest ≥ 8, Swagger. Git: папка learning-log/week-18/ , feature-ветки по роутерам; тег week-18-done . День 120 (Пн): SQLAlchemy — модели и сессии Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Library REST API Теория SQLAlchemy 2.0 — современный ORM для Python. DeclarativeBase, Mapped[type] и mapped_column() задают модели типобезопасно. Engine — подключение к PostgreSQL; SessionLocal — фабрика сессий. Сессия — unit of work: session.add(obj) , co…", "snippet": "Неделя 18: SQLAlchemy ORM + FastAPI Цель недели: построить типобезопасный REST API на Python с ORM и автодокументацией. "}, {"route": "week-19", "title": "Неделя 19: Node.js + Express REST API", "text": "Неделя 19: Node.js + Express REST API Цель недели: построить REST API на JavaScript в среде Node.js с Express и PostgreSQL. Литература: Node.js Docs , Express Guide , node-postgres Проект недели: Express Notes API — layered Express API, Zod, PostgreSQL, Postman collection. Git: папка learning-log/week-19/ , ветки feature/routes , feature/pg ; тег week-19-done . День 127 (Пн): Node.js — среда и модули Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Express Notes API Теория Node.js — среда выполнения JavaScript вне браузера. Нет DOM и window , зато есть process , встроенные модули и npm-экосистема. Backend на Node разделяет язык с фронтендом — один TypeScript/JavaScript на обе стороны, но ru…", "snippet": "Неделя 19: Node.js + Express REST API Цель недели: построить REST API на JavaScript в среде Node.js с Express и PostgreS"}, {"route": "week-20", "title": "Неделя 20: Auth, безопасность, тестирование", "text": "Неделя 20: Auth, безопасность, тестирование Цель недели: реализовать JWT-аутентификацию, изучить OWASP и написать базовые тесты (Vitest + pytest). Литература: JWT.io , OWASP Top 10 , Vitest , pytest Проект недели: Secure Notes — JWT auth, bcrypt, rate limit, React client, pytest + Vitest. Git: папка learning-log/week-20/ , отдельные коммиты backend/frontend; тег week-20-done . День 134 (Пн): Аутентификация и хеширование паролей Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Secure Notes Теория Authentication отвечает на вопрос «кто ты?» — проверка личности (логин/пароль). Authorization — «что тебе можно?» — права на ресурсы. Не путай: успешный login не означает доступ ко всем endpoints. П…", "snippet": "Неделя 20: Auth, безопасность, тестирование Цель недели: реализовать JWT-аутентификацию, изучить OWASP и написать базовы"}, {"route": "week-21", "title": "Неделя 21: Full-Stack интеграция и Docker", "text": "Неделя 21: Full-Stack интеграция и Docker Цель недели: связать React-фронтенд с бэкендом и упаковать всё в Docker Compose. Литература: Docker Docs , docker-compose , Vite Env Проект недели: Task Manager Docker — React + API + PostgreSQL в docker-compose , healthchecks, seed. Git: папка learning-log/week-21/ , monorepo или два репо в одной папке; тег week-21-done . День 141 (Пн): Связка Frontend + Backend Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Task Manager Docker Теория Full-stack начинается там, где фронтенд и бэкенд встречаются в браузере. Same-origin policy: localhost:5173 (Vite) и localhost:3000 (API) — разные origins. Браузер блокирует cross-origin fetch без заголовков CORS от…", "snippet": "Неделя 21: Full-Stack интеграция и Docker Цель недели: связать React-фронтенд с бэкендом и упаковать всё в Docker Compos"}, {"route": "week-22", "title": "Неделя 22: DevHub Capstone — финальный full-stack проект", "text": "Неделя 22: DevHub Capstone — финальный full-stack проект Цель недели: собрать, протестировать и задеплоить DevHub — единый capstone, объединяющий весь стек 22 недель обучения. Литература: docs/projects.md — DevHub Capstone , Vercel Docs , Render Docs , GitHub Actions Проект недели: DevHub Capstone — персональная платформа разработчика: дашборд + заметки + задачи + GitHub API. Git: папка learning-log/week-22-capstone/ , feature-ветки по дням 149–153; тег week-22-done + обновление GitHub Profile README. Не начинайте с нуля в последний день. Планируйте в день 148, кодите 149–153, деплой и портфолио — в день 154. Полная спецификация MVP, стека и критериев сдачи — в каталоге проектов . День 148 (Пн): Планирование DevHub Capstone Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревь…", "snippet": "Неделя 22: DevHub Capstone — финальный full-stack проект Цель недели: собрать, протестировать и задеплоить DevHub — един"}, {"route": "intro", "title": "Введение", "text": "Введение Добро пожаловать в web-roadmap — 22-недельный путь к junior full-stack разработчику. Главная цель Перестать быть «вайбкодером» и стать инженером, который понимает, почему код работает , и может переписать его без ИИ. Главный враг — иллюзия компетентности. Туториал посмотрел — кажется, всё ясно. Мы ломаем эту иллюзию ежедневной практикой . Принцип прогрессии Наглядное → Логика → Абстракции → Системы HTML/CSS → JS → React/TS → Full-Stack + DevOps Не перепрыгивайте: слабый фундамент в HTML/JS превратит React и бэкенд в мучение. Фазы маршрута Фазы Недели Фокус Вёрстка 1–3 HTML, CSS, адаптив Git & workflow 1, 4 Git с дня 1; нед. 4 — advanced, PR, OSS Язык браузера 5–10 JS, async, TypeScript Фронтенд 11–14 React, SPA-проект Python & данные 15–18 Python, SQL, FastAPI JS-бэкенд 19…", "snippet": "Введение Добро пожаловать в web-roadmap — 22-недельный путь к junior full-stack разработчику. Главная цель Перестать быт"}, {"route": "start", "title": "Начало работы", "text": "Начало работы Сколько времени Параметр Значение Длительность 22 недели (154 дня) Нагрузка ~5–7 ч/день (полный) или ~3–4 ч (лайт) Проекты 22 недельных + 1 capstone (неделя 22) Итог Junior full-stack portfolio + понимание стека Если у вас меньше времени — растяните недели; не пропускайте проекты недели . Каталог: projects.md . Git с первого дня (обязательно) До недели 1, день 0 вы создаёте публичный репозиторий learning-log на GitHub. В день 1 недели 1 вы коммитите свой первый index.html . Это не «потом разберусь» — Git часть учебного процесса с первой строки HTML. Быстрый старт Git # 1. GitHub → New repository → learning-log # Public, БЕЗ README / .gitignore / license (пустой репозиторий под вашим аккаунтом) git clone https://github.com/<ваш-логин>/learning-log.git cd learning-log # 2…", "snippet": "Начало работы Сколько времени Параметр Значение Длительность 22 недели (154 дня) Нагрузка ~5–7 ч/день (полный) или ~3–4 "}, {"route": "projects", "title": "Каталог проектов: 22 + Capstone", "text": "Каталог проектов: 22 + Capstone Каждая неделя заканчивается работающим проектом в вашем репозитории learning-log . Недели 1–21 накапливают навыки; неделя 22 — единый крупномасштабный capstone со всем стеком. Правило: проект недели = отдельная папка week-NN/ (или week-NN-project-name/ ), тег week-NN-done , README внутри папки. Обзор Нед. Проект Стек Папка 01 Portfolio Landing HTML, a11y, формы week-01/ 02 Styled Blog Post CSS, design tokens week-02/ 03 SaaS Landing Flexbox, Grid, адаптив week-03/ 04 OSS Workflow Kit Git, PR, GitHub Pages week-04/ 05 Console Task Manager Vanilla JS, массивы week-05/ 06 DOM Todo App DOM, события week-06/ 07 Notes Dashboard ES modules, Fetch, storage week-07/ 08 Movie Catalog async/await, REST API week-08/ 09 Library System OOP, паттерны, Observer week-09/ 10 …", "snippet": "Каталог проектов: 22 + Capstone Каждая неделя заканчивается работающим проектом в вашем репозитории learning-log . Недел"}, {"route": "cheatsheet-html", "title": "HTML & CSS — шпаргалка", "text": "HTML & CSS — шпаргалка После недель 1–3. Полный маршрут HTML семантика header → nav → main → section/article → aside → footer Один h1 на страницу, иерархия без пропусков label[for] ↔ input[id] img + alt ; декоративное → alt=\"\" Формы: required , pattern , fieldset / legend Box model content → padding → border → margin *, *::before, *::after { box-sizing: border-box; } Flexbox .container { display: flex; gap: 1rem; justify-content: center; align-items: center; } .item { flex: 1; } /* grow */ Grid .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1rem; } Адаптив /* mobile-first */ .hero { font-size: clamp(1.5rem, 4vw, 2.5rem); } @media (min-width: 768px) { ... } Design tokens :root { --color-bg: #050508; --space-md: 1rem; --radius: 12px; }", "snippet": "HTML & CSS — шпаргалка После недель 1–3. Полный маршрут HTML семантика header → nav → main → section/article → aside"}, {"route": "cheatsheet-js", "title": "JavaScript & TypeScript — шпаргалка", "text": "JavaScript & TypeScript — шпаргалка После недель 5–10. Типы и сравнение Примитивы: string , number , boolean , null , undefined , bigint , symbol Всегда === , не == const по умолчанию; let если переприсвоение Массивы arr.map(x => x * 2) arr.filter(x => x.done) arr.find(x => x.id === id) arr.reduce((sum, x) => sum + x, 0) // slice — копия; splice — мутирует Async async function load() { const res = await fetch(url); if (!res.ok) throw new Error(res.status); return res.json(); } Event Loop (упрощённо) sync code → microtasks (Promise) → macrotasks (setTimeout) → render Модули // utils.js export function fmt(d) { ... } // app.js import { fmt } from './utils.js'; TypeScript interface User { id: number; name: string } type Status = 'active' | 'done'; function wrap<T>(x: T):…", "snippet": "JavaScript & TypeScript — шпаргалка После недель 5–10. Типы и сравнение Примитивы: string , number , boolean , null "}, {"route": "cheatsheet-react", "title": "React — шпаргалка", "text": "React — шпаргалка После недель 11–14. Компонент type Props = { title: string; onSave: () => void }; export function Card({ title, onSave }: Props) { return <article><h2>{title}</h2><button onClick={onSave}>Save</button></article>; } State & effects const [count, setCount] = useState(0); useEffect(() => { document.title = `Tasks: ${count}`; return () => { /* cleanup */ }; }, [count]); Формы (controlled) const [text, setText] = useState(''); <input value={text} onChange={e => setText(e.target.value)} /> Router <Routes> <Route path="/" element={<Home />} /> <Route path="/tasks/:id" element={<TaskDetail />} /> </Routes> Context const ThemeCtx = createContext<'light'|'dark'>('…", "snippet": "React — шпаргалка После недель 11–14. Компонент type Props = { title: string; onSave: () => void }; export function C"}, {"route": "cheatsheet-sql", "title": "SQL & PostgreSQL — шпаргалка", "text": "SQL & PostgreSQL — шпаргалка После недели 17. CRUD SELECT id, title FROM tasks WHERE user_id = $1 ORDER BY created_at DESC; INSERT INTO tasks (title, user_id) VALUES ($1, $2) RETURNING *; UPDATE tasks SET done = true WHERE id = $1 AND user_id = $2; DELETE FROM tasks WHERE id = $1 AND user_id = $2; JOIN SELECT b.title, a.name FROM books b JOIN authors a ON b.author_id = a.id; Индексы CREATE INDEX idx_tasks_user ON tasks(user_id); EXPLAIN ANALYZE SELECT ...; Нормализация (кратко) 1NF: атомарные значения 2NF: нет частичных зависимостей от составного ключа 3NF: нет транзитивных зависимостей Транзакции BEGIN; -- ops COMMIT; -- или ROLLBACK; Миграции Версионируй схему: schema.sql , migrations/001_*.sql , seed отдельно.", "snippet": "SQL & PostgreSQL — шпаргалка После недели 17. CRUD SELECT id, title FROM tasks WHERE user_id = $1 ORDER BY created_a"}, {"route": "cheatsheet-backend", "title": "FastAPI & Backend — шпаргалка", "text": "FastAPI & Backend — шпаргалка После недель 18–21. FastAPI минимум from fastapi import FastAPI, Depends, HTTPException app = FastAPI() @app.get("/api/v1/tasks") def list_tasks(db = Depends(get_db)): return db.query(Task).all() Pydantic class TaskCreate(BaseModel): title: str = Field(min_length=1, max_length=200) JWT flow register → hash password (bcrypt) login → issue access token (short) + optional refresh protected route → Depends(get_current_user) Express слои routes → controllers → services → db middleware: cors, helmet, rateLimit, errorHandler Docker Compose services: db: { image: postgres:16, environment: {...}, volumes: [...] } api: { build: ./backend, depends_on: [db], ports: ["8000:8000"] } web: { build: ./frontend, ports: ["5173:80"] } Security ch…", "snippet": "FastAPI & Backend — шпаргалка После недель 18–21. FastAPI минимум from fastapi import FastAPI, Depends, HTTPExceptio"}] \ No newline at end of file diff --git a/docs/w/00.html b/docs/w/00.html index e5d9dd7..207a7b8 100644 --- a/docs/w/00.html +++ b/docs/w/00.html @@ -29,9 +29,12 @@

День 0.1: Инструменты

Связь с проектом: стабильная среда для всех следующих недель

Теория

-

Веб-разработка начинается не с кода, а со среды: редактор, браузер с DevTools, терминал, Git. Эти инструменты останутся с вами на годы.

-

VS Code — редактор с встроенным терминалом и Git. Chrome DevTools — Elements (DOM/CSS), Console (ошибки JS), Network (запросы). Git — история изменений; без него нет портфолио.

-

Ключевая мысль: стабильная среда важнее скорости «сразу писать код».

+

Веб-разработка начинается не с кода, а со среды: редактор, браузер с DevTools, терминал, Git. Эти инструменты останутся с вами на годы, поэтому час, потраченный сегодня на настройку, окупится десятки раз позже.

+

Удобная мысленная модель: редактор — мастерская, где вы создаёте вещь; браузер с DevTools — рентген, который показывает, что получилось на самом деле; терминал — пульт, откуда команды отдаются инструментам напрямую, а не кликами мыши; Git — машина времени, которая помнит каждую версию вашей работы.

+

VS Code — редактор с встроенным терминалом и подсветкой Git-изменений прямо в файлах. Chrome DevTools — три вкладки на каждый день: Elements показывает живое дерево DOM и применённые CSS-правила, Console выводит ошибки JavaScript, Network — что загрузила страница и сколько это заняло. Git — история изменений; без него нет портфолио и нет пути назад, если что-то сломалось.

+

Пример: через несколько недель вы случайно удалите важный кусок CSS и не заметите это сразу — git diff покажет ровно те строки, что изменились со вчерашнего коммита, и восстановить код можно за секунды вместо часа гаданий.

+

Частая ошибка новичков — писать код без Git «чтобы не тратить время на настройку», откладывая репозиторий «на потом, когда будет что показать». Тогда первые недели прогресса нигде не задокументированы. Такая же ошибка — отлаживать вёрстку методом «поменял файл — обновил страницу — посмотрел», хотя Elements с редактированием стилей на лету делает это быстрее.

+

Ключевая мысль: стабильная среда важнее скорости «сразу писать код» — сегодняшняя практика единственный раз в маршруте посвящена только настройке, чтобы дальше ничего не отвлекало от обучения.

Читать: Как начать — таблица инструментов.

Практика (полный трек)

    @@ -60,9 +63,12 @@

    День 0.2: GitHub и свой learning-log

    Связь с проектом: публичное портфолио с дня 1 недели 1

    Теория

    -

    Публичный learning-log — портфолио в процессе. Рекрутер видит дисциплину: коммиты, сообщения, рост по неделям — не только финальный zip.

    -

    Репозиторий создаёте под своим аккаунтом, пустой (без README от GitHub), затем клонируете себе. Не клонируйте чужой learning-log — это должен быть ваш граф коммитов.

    -

    Ключевая мысль: репозиторий появляется до первой строки HTML.

    +

    Публичный learning-log — портфолио в процессе, а не готовая витрина. Рекрутер, который откроет ваш GitHub через полгода, видит не только финальный код, но и дисциплину: регулярные коммиты, внятные сообщения, заметный рост качества от недели 1 к неделе 20. Это рассказывает историю лучше, чем строчка в резюме.

    +

    Мысленная модель: репозиторий — дневник разработчика, а не архив готовых работ. Каждый коммит — запись «что сделано и зачем», а вместе они складываются в график активности на странице профиля GitHub. Пустые недели в этом графике так же красноречивы, как и активные.

    +

    Репозиторий создаёте под своим аккаунтом, пустым (без README, лицензии и .gitignore от GitHub — их вы добавите сами локально, чтобы первый коммит был осмысленным, а не автосгенерированным), затем клонируете себе на компьютер. Важно не путать: клонировать нужно свой пустой репозиторий, а не чужой существующий learning-log — иначе история коммитов будет принадлежать другому человеку, и смысл портфолио теряется.

    +

    Почему это важно для всего маршрута: начиная с недели 1 каждый день заканчивается коммитом в эту же папку. Если репозиторий настроен неправильно сегодня — с чужой историей или без .gitignore — проблему придётся решать посреди недели 1, отвлекаясь от HTML.

    +

    Частое заблуждение — думать, что показывать портфолио стоит только после «идеального» результата, поэтому можно закоммитить всё одним большим коммитом в конце. На деле частые маленькие коммиты с понятными сообщениями (feat: add contact form, а не fix) сами по себе сигнал профессионализма — и заметны раньше, чем содержимое кода.

    +

    Ключевая мысль: репозиторий появляется до первой строки HTML — сегодняшняя практика это подтверждает: вы создаёте learning-log, .gitignore и README.md ещё до того, как напишете хоть один тег.

    Практика (полный трек)

    1. Аккаунт GitHub (если нет) + 2FA по возможности
    2. @@ -101,7 +107,8 @@

      День 0.3: Как учиться по маршрут Связь с проектом: выбрать полный или лайт-трек до недели 1

      Теория

      -

      Каждый учебный день недель 1–22:

      +

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

      +

      Каждый учебный день недель 1–22 устроен одинаково:

      @@ -132,8 +139,9 @@

      Теория

      -

      Полный трек (~5–7 ч/день): максимум глубины. Лайт (~3–4 ч): теория + лайт-практика + Git; проект недели — в урезанном DoD из каталога.

      -

      Протокол «анти-вайбкодер»: ИИ объясняет концепцию или ревьюит ваш код. Не пишет за вас.

      +

      Полный трек (~5–7 ч/день): максимум глубины, все пункты практики, углублённое ревью. Лайт (~3–4 ч): теория читается полностью, практика — только MVP-подмножество, коммит обязателен; проект недели сдаётся в урезанном DoD (Definition of Done) из каталога проектов — согласованный меньший набор требований, а не «сделаю потом».

      +

      Почему это важно для следующих недель: если сегодня не разобраться, чем полный трек отличается от лайт, велик риск на неделе 5 обнаружить накопившееся отставание, которое сложно объяснить — просто не был понятен ожидаемый объём практики. Пример: студент на лайт-треке, который в день 3 недели 1 делает только MVP-пункты вместо всех пунктов «полного трека», не отстаёт — он следует своему треку, если проект недели в итоге собран по лайт-DoD.

      +

      Протокол «анти-вайбкодер» — отдельное важное правило: ИИ-ассистент в этом маршруте объясняет концепцию или ревьюит уже написанный вами код, но не пишет решение за вас. Частая ошибка новичков — попросить ИИ «сделай форму валидации» и скопировать ответ: код появится, а навык — нет, и это станет заметно на итоговом проекте. Сегодняшняя практика — прочитать introduction и каталог проектов, чтобы осознанно выбрать трек, а не выяснять правила на ходу в понедельник.

      Читать: - Введение - Каталог 22 проектов

      diff --git a/docs/w/01.html b/docs/w/01.html index 88c2fe8..e6adcaf 100644 --- a/docs/w/01.html +++ b/docs/w/01.html @@ -64,8 +64,8 @@

      Литература (обязательно + по желанию)


      День 0 (до понедельника): Git и GitHub — подготовка

      -

      Время (полный): ~35м теория · ~1.5ч практика · ~10м Git · ~15м ревью
      -Время (лайт): ~15м теория · ~40м практика (MVP) · ~10м Git
      +

      Время (полный): ~55м теория · ~1.5ч практика · ~10м Git · ~15м ревью
      +Время (лайт): ~25м теория · ~40м практика (MVP) · ~10м Git
      Связь с проектом: шаг к Portfolio Landing

      Если Git уже установлен и аккаунт GitHub есть — пройди чеклист и переходи к дню 1.

      @@ -73,7 +73,10 @@

      Теория

      Система контроля версий (VCS) решает проблему, с которой каждый разработчик сталкивается рано: «что я менял, когда и зачем?». Без VCS папка проекта превращается в index_final_v3_REAL.html. Git хранит не отдельные патчи, а снимки всего проекта в момент коммита — как фотография комнаты, а не список «переставили стул на 3 см влево». Это позволяет мгновенно откатиться к любому состоянию, сравнить две версии и работать параллельно в ветках.

      Рабочий процесс Git строится вокруг трёх зон. Working directory — файлы на диске, которые ты редактируешь прямо сейчас. Команда git add переносит выбранные изменения в staging (индекс) — зону подготовки: «вот это точно войдёт в следующий коммит». git commit фиксирует снимок staging в repository — локальной базе истории. Мысленная модель: черновик на столе → выбранные листы в папку «на подпись» → подписанный документ в архив.

      GitHub — это удалённое зеркало репозитория плюс социальная платформа. Публичный learning-log с осмысленной историей коммитов — живое портфолио: рекрутер видит не только код, но и то, как ты думаешь и работаешь.

      -

      Ключевая мысль: коммит — это именованный снимок проекта, а не просто «сохранить файл».

      +

      Почему это критично для всех следующих 22 недель: каждый день маршрута заканчивается коммитом, и от того, насколько уверенно ты сегодня освоишь addcommitpush, зависит, будет ли Git помогать или пугать всю дорогу. На неделе 6 появятся ветки для фич, дальше — пул-реквесты и код-ревью; без твёрдой базы трёх зон эти темы превращаются в магию вместо инструмента.

      +

      Конкретный пример рабочего цикла: правишь index.html, git status показывает файл как изменённый (working directory), git add index.html переносит его в staging, git commit -m "..." создаёт снимок в истории, git push отправляет его на GitHub — до этого момента изменения видны только тебе локально.

      +

      Частое заблуждение новичков — считать, что git add уже «сохраняет» изменения, и после него можно закрыть терминал. На деле без git commit изменения остаются в staging и никуда не «доезжают»; а без git push коммит остаётся только на твоём компьютере и не появится на GitHub, даже если локально git log показывает его.

      +

      Ключевая мысль: коммит — это именованный снимок проекта, а не просто «сохранить файл»; сегодняшняя практика — прогнать этот цикл от установки Git до первого git push вручную, чтобы завтра, в день 1, писать index.html и коммитить его уже не задумываясь о механике.

      Читать: - Pro Git: Введение — зачем VCS: история, откат, ветки

      Практика (полный трек)

      @@ -118,8 +121,8 @@

      Практика (лайт / MVP)

      День 1 (Mon): Структура документа, первый index.html, первый коммит страницы

      -

      Время (полный): ~1.5ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~35м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Portfolio Landing

      Теория

      @@ -127,7 +130,10 @@

      Теория

      Каждый документ начинается с <!DOCTYPE html>, который переключает браузер в standards mode — предсказуемое поведение вёрстки. Без DOCTYPE старые браузеры могут включить quirks mode и интерпретировать CSS иначе. В <head> живут метаданные: кодировка (charset), viewport для мобильных, заголовок вкладки. В <body> — всё, что видит пользователь.

      Элементы делятся на блочные и строчные. Блочные (p, h1, ul) занимают всю ширину строки и начинаются с новой линии — как абзацы в книге. Строчные (span, a, img) текут внутри строки, как слова в предложении. Заголовки h1h6 задают иерархию разделов, а не размер шрифта: один логический h1 на страницу, затем h2 для подразделов. Прыжок с h1 сразу на h3 — как оглавление, где после главы 1 идёт 1.3 без главы 2.

      Атрибуты дополняют теги: id — уникальный якорь (один на страницу), class — группа для стилей, href и src — адреса ссылок и ресурсов. У img атрибут alt обязателен, если картинка несёт смысл — иначе скринридер и поисковик не поймут, что на изображении.

      -

      Ключевая мысль: HTML описывает структуру и смысл; браузер из неё строит DOM-дерево.

      +

      Мысленная модель, которая пригодится на всех следующих неделях: HTML — это скелет, CSS (неделя 2) — одежда и внешний вид, JavaScript (неделя 4+) — мышцы и поведение. Скелет должен быть правильным сам по себе, ещё до того, как на него что-то надето: скринридер и поисковик читают именно разметку, а не то, как страница выглядит визуально после стилизации.

      +

      Конкретный пример: если сверстать блок «Обо мне» через <div><div>Обо мне</div><div>Текст...</div></div>, страница может выглядеть нормально после CSS, но программа чтения с экрана объявит просто «группа, группа» — пользователь не поймёт, что перед ним заголовок раздела. Замена на <h2>Обо мне</h2><p>Текст...</p> решает проблему без единой строчки CSS.

      +

      Частое заблуждение новичков — писать <div> и <span> для всего подряд «а потом стилями сделаю красиво», откладывая выбор семантики на потом. На деле семантика закладывается сразу: разметка описывает смысл контента независимо от того, как он будет оформлен, и переписывать структуру после того, как всё завязано на классы, дороже, чем сделать правильно с первого раза. Сегодняшняя практика — первый index.html — это и есть тренировка такого выбора: заголовки по иерархии, nav для навигации, осмысленный alt у изображения.

      +

      Ключевая мысль: HTML описывает структуру и смысл; браузер из неё строит DOM-дерево, а CSS и JS лишь надстраиваются сверху.

      Читать: - MDN: Введение в HTML — разметка описывает смысл, браузер строит DOM-дерево

      Практика (полный трек)

      @@ -156,7 +162,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      Git

      cd learning-log
       git add week-01/index.html week-01/README.md
      @@ -173,14 +179,18 @@ 

      Ловушки


      День 2 (Tue): Семантическая разметка

      -

      Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Portfolio Landing

      Теория

      Семантика в HTML — это выбор тега, который точно описывает роль элемента, а не просто «коробку для стилей». <div> ничего не говорит о содержимом; <nav> явно объявляет: здесь навигация. Браузер, скринридер и поисковик читают эту разметку и строят карту страницы. Пользователь с программой чтения с экрана может прыгнуть сразу к main, минуя шапку и меню — если ты их правильно разметил.

      Landmark-элементы — ориентиры на странице: header (шапка), nav (меню), main (основной уникальный контент), footer (подвал). На странице должен быть ровно один main. nav — только для навигационных ссылок, не для любого списка ссылок в тексте. Страница с семантической разметкой читается логично даже без CSS — это хороший тест: отключи стили и проверь, понятна ли структура.

      section группирует тематически связанный контент с заголовком (блок «О себе», «Навыки»). article — самодостаточная единица: пост в блоге, карточка товара, новость — то, что можно вынести в RSS отдельно. aside — боковое дополнение к основному потоку: виджет «сейчас изучаю», реклама, сноски. Пара figure + figcaption связывает иллюстрацию с подписью; элемент time с атрибутом datetime даёт машиночитаемую дату для календарей и микроразметки.

      +

      Мысленная модель: представь страницу как здание с указателями. header — вывеска у входа, nav — карта этажей у лифта, main — сам этаж с содержимым, aside — информационный стенд в коридоре, footer — табличка на выходе. Указатели помогают ориентироваться даже тому, кто не видит всё здание целиком — например, идёт по нему на ощупь, как скринридер идёт по DOM.

      +

      Почему это важно дальше: на неделе 6 ты добавишь JavaScript, который будет искать элементы по структуре страницы (document.querySelector('main'), обработчики на nav a), а на неделях с React — компоненты будут возвращать именно такую семантическую разметку. Если сегодня привыкнуть мыслить landmark-ами, а не «div с классом wrapper», работа с фреймворками пойдёт быстрее.

      +

      Пример: <div class="post"><div class="post-title">Заголовок</div><div class="post-date">1 августа</div></div> технически работает, но <article><h2>Заголовок</h2><time datetime="2026-08-01">1 августа</time></article> даёт браузеру и поисковику готовую структуру поста без единой строчки JS.

      +

      Частое заблуждение — использовать section для любого визуального блока с отступом. section уместен только когда у контента есть собственный заголовок и он тематически целостен; блок для чисто визуального разделения (например, обёртка для центрирования) так и остаётся div. Сегодня в практике ты рефакторишь вчерашний index.html именно с этим фильтром: «у этого блока есть заголовок и смысл, или это просто обёртка для стилей?»

      Ключевая мысль: правильный тег — это документация для людей и машин; div — последний выбор, не первый.

      Читать: - MDN: Семантика — тег несёт смысл для браузера, скринридера, SEO

      @@ -206,7 +216,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

      Git

      git add week-01/index.html
       git commit -m "week 01 day 2: refactor to semantic landmarks and article"
      @@ -215,15 +225,19 @@ 

      Git


      День 3 (Wed): Ссылки, изображения, медиа

      -

      Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Portfolio Landing

      Теория

      Многостраничный сайт связывается ссылками и путями к ресурсам. Относительные пути (./about.html, ../images/photo.jpg) привязаны к структуре папок проекта, а не к домену — перенеси папку на другой хостинг, и ссылки продолжат работать. Абсолютные URL с доменом (например example.com/page) нужны для внешних ресурсов. Якорные ссылки (#section-id) прыгают к элементу с соответствующим id на той же странице.

      Изображения — отдельная дисциплина доступности и производительности. Атрибут alt описывает смысл картинки для тех, кто её не видит. Декоративное изображение получает alt="" (пустой), чтобы скринридер его пропустил. Не дублируй текст из figcaption в alt — это раздражает при озвучивании дважды. Атрибут loading="lazy" откладывает загрузку картинок ниже первого экрана, ускоряя начальную отрисовку. Пара srcset + sizes позволяет браузеру выбрать подходящий размер файла под экран — меньше трафика на мобильном.

      Видео встраивается тегом <video> с controls для панели управления и poster — превью до воспроизведения. Текст внутри тега — fallback для старых браузеров: «Ваш браузер не поддерживает видео».

      -

      Ключевая мысль: alt — не украшение, а часть контента; пустой alt уместен только для декора.

      +

      Мысленная модель для путей: относительный путь — это инструкция «иди отсюда», а не «иди по этому адресу в интернете». Если файл about.html лежит рядом с index.html, ссылка ./about.html сработает где угодно — на твоём компьютере, на GitHub Pages, на любом хостинге — потому что она описывает взаимное расположение файлов, а не конкретный домен.

      +

      Почему это важно дальше: на неделе 9+ с системами сборки (Vite, Webpack) пути к изображениям и скриптам будут переписываться автоматически, но принцип «относительно текущего файла» останется тем же — непонимание разницы ./, ../ и / в начале пути — частый источник «битых картинок после деплоя» даже у опытных разработчиков.

      +

      Конкретный пример: галерея с 10 фотографиями по 3 МБ каждая без loading="lazy" загрузит все 30 МБ сразу при открытии страницы, даже если пользователь видит только первые три — это заметно тормозит мобильный интернет. С loading="lazy" браузер подгружает картинку только когда она приближается к области видимости при скролле.

      +

      Частое заблуждение — считать, что alt="" означает «забыл добавить описание». На самом деле пустой alt — осознанное решение для декоративной картинки (орнамент, разделитель), и скринридер тогда молча её пропускает; отсутствие атрибута alt вообще — это ошибка, при которой скринридер зачитывает весь путь к файлу. В сегодняшней практике, добавляя аватар и галерею, различай эти два случая осознанно.

      +

      Ключевая мысль: alt — не украшение, а часть контента; пустой alt уместен только для декора, а не как способ сэкономить время на описании.

      Читать: - MDN: Изображения в HTML - MDN: Responsive images

      @@ -250,7 +264,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

      Git

      git add week-01/
       git commit -m "week 01 day 3: multi-page site with gallery and media"
      @@ -259,15 +273,19 @@ 

      Git


      День 4 (Thu): Формы — основы

      -

      Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Portfolio Landing

      Теория

      Форма — мост между пользователем и сервером: собирает ввод и отправляет его. Даже на статическом сайте без бэкенда форма полезна для изучения: можно увидеть в DevTools → Network, какие данные ушли бы при submit. Атрибут action задаёт URL назначения; без него отправка идёт на текущий адрес страницы.

      Связка label[for="field-id"] + input[id="field-id"] — фундамент доступности форм. Клик по подписи фокусирует поле: удобно на мобильном и критично для пользователей скринридеров. Атрибут name на каждом поле — ключ, под которым значение попадёт в данные формы при отправке. Без name поле просто игнорируется.

      Группировка через fieldset и legend объединяет связанные поля (например, radio-кнопки) с общим заголовком. У radio-кнопок в одной группе должен быть одинаковый name — иначе браузер не поймёт, что выбор взаимоисключающий. Внимание к типам кнопок: button без type внутри формы по умолчанию ведёт себя как submit и отправляет форму. Для обычной кнопки явно укажи type="button".

      -

      Ключевая мысль: каждое поле — с видимым label; name — имя данных при отправке.

      +

      Мысленная модель: форма — это посылка на почте. name каждого поля — надпись на коробке («имя», «email»), value — содержимое коробки, а action — адрес получателя. Если на коробке нет надписи (name отсутствует), почта её просто не примет — данные потеряются ещё до отправки.

      +

      Почему это важно дальше: на неделях 11+ с бэкендом ты будешь получать те самые пары name: value на сервере (req.body.email) — если сегодня не разобраться, откуда берутся эти имена полей, серверная обработка форм превратится в чёрный ящик. А на неделе 6 с JavaScript ты научишься перехватывать submit и отправлять данные без перезагрузки страницы (fetch), но структура данных останется той же, что задаёт HTML сегодня.

      +

      Конкретный пример: два radio-инпута с name="contact-method" и разными value («email», «phone») образуют одну группу, где выбор одного автоматически снимает выбор другого. Если по ошибке дать им разные name, оба чекбокса смогут быть выбраны одновременно — форма перестанет быть «выбери один вариант».

      +

      Частое заблуждение новичков — считать, что placeholder заменяет label, ведь текст и так виден в поле. На деле placeholder исчезает при вводе и не связан с полем программно — скринридер его может не объявить как подпись. В сегодняшней практике каждое поле должно получить настоящий видимый label, даже если рядом есть placeholder для дополнительной подсказки формата.

      +

      Ключевая мысль: каждое поле — с видимым label; name — имя данных при отправке, а не декоративный атрибут.

      Читать: - MDN: Your first form

      Практика (полный трек)

      @@ -301,15 +319,19 @@

      Git


      День 5 (Fri): Валидация форм

      -

      Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Portfolio Landing

      Теория

      HTML5 принёс встроенную валидацию — браузер проверяет поля до отправки без единой строки JavaScript. Атрибуты required, minlength, pattern, type="email" задают правила; при нарушении submit блокируется, и браузер показывает подсказку. За кулисами работает Constraint Validation API: у каждого поля есть объект validity со флагами (valueMissing, patternMismatch и др.) и свойство validationMessage с текстом ошибки.

      В CSS псевдокласс :invalid позволяет подсветить проблемное поле — но осторожно: поле считается :invalid и до первого ввода, если оно required. Часто комбинируют с :user-invalid или вешают стили после попытки submit. Атрибут placeholder — серый текст-подсказка внутри поля, который исчезает при вводе. Он не заменяет label: пользователь, начав печатать, уже не видит, что от него хотели. datalist даёт выпадающие подсказки, но не ограничивает ввод — в отличие от select.

      -

      Клиентская валидация — удобство и ранняя обратная связь, но не защита: злоумышленник обойдёт её за секунду. На сервере проверять всё равно обязательно.

      -

      Ключевая мысль: placeholder — подсказка, label — подпись; не путай их роли.

      +

      Клиентская валидация — удобство и ранняя обратная связь, но не защита: злоумышленник обойдёт её за секунду, отправив запрос напрямую в обход браузера. На сервере проверять всё равно обязательно.

      +

      Мысленная модель: pattern и required — это турникет на входе в метро, а серверная валидация — охрана внутри здания. Турникет удобен и отсекает большинство случайных нарушителей, но полагаться только на него нельзя — до сервера с реальной проверкой долетит что угодно, если турникет обойти напрямую через инструменты разработчика или curl.

      +

      Почему это важно дальше: на неделях 11–14 с бэкендом ты будешь писать серверную валидацию тех же самых полей — зная уже сегодня, какие правила выражает pattern и required на клиенте, легче понять, зачем дублировать похожую логику на сервере (спойлер: потому что клиенту нельзя доверять).

      +

      Конкретный пример: pattern="[A-Za-z0-9_]{3,20}" для логина не пропустит пробелы и спецсимволы, а браузер покажет стандартную подсказку — но без title="Только буквы, цифры и подчёркивание, 3-20 символов" пользователь не поймёт, что именно не так, увидит просто «Please match the requested format».

      +

      Частое заблуждение — думать, что type="email" полностью гарантирует валидный email. На деле встроенная проверка лишь требует наличие @ и домена по упрощённому шаблону — a@a пройдёт, а несуществующий домен ivan@nosuchdomain123.zzz тоже пройдёт, ведь синтаксически он корректен. Реальную проверку существования email делает только сервер, отправляя письмо-подтверждение.

      +

      Ключевая мысль: placeholder — подсказка, label — подпись; не путай их роли, и не путай клиентскую валидацию с настоящей защитой данных.

      Читать: - MDN: Form validation

      Практика (полный трек)

      @@ -334,7 +356,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      git add week-01/
       git commit -m "week 01 day 5: registration form with HTML5 validation"
      @@ -348,15 +370,19 @@ 

      Ловушки


      День 6 (Sat): Доступность (a11y)

      -

      Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Portfolio Landing

      Теория

      Доступность (accessibility, a11y) — это не «галочка для инвалидов», а качество интерфейса для всех: плохой контраст мешает читать при ярком солнце, а чёткая навигация с клавиатуры спасает, когда мышь сломалась. Фреймворк POUR задаёт четыре принципа: контент должен быть воспринимаем (Perceivable), управляем (Operable), понятен (Understandable) и устойчив к разным технологиям (Robust).

      Клавиатурная навигация — базовый тест. Порядок Tab следует порядку элементов в DOM, а не визуальному расположению на экране. Не ставь положительный tabindex без веской причины — это ломает естественный порядок. Skip link — первая фокусируемая ссылка «Перейти к содержимому», ведущая к #main-content; пользователь скринридера не слушает меню на каждой странице заново.

      Контраст текста и фона по WCAG AA — минимум 4.5:1 для обычного текста и 3:1 для крупного. Проверяй через WebAIM Contrast Checker, а не «на глаз». ARIA-атрибуты (aria-label, role) дополняют HTML, когда нативного элемента нет — но первое правило ARIA: не используй ARIA, если подходит обычный тег (button вместо div с role="button").

      -

      Ключевая мысль: если страницу нельзя пройти Tab-ом — она недоступна, даже с идеальным дизайном.

      +

      Мысленная модель: представь, что весь сайт нужно пройти с закрытыми глазами и только с клавиатурой — это буквально то, как его использует часть аудитории. Всё, что требует «просто увидеть цвет» или «просто кликнуть мышкой точно в маленькую область», для такого пользователя не существует. a11y — это проектирование сразу для этого сценария, а не патч поверх готового интерфейса.

      +

      Почему это важно дальше: вся вёрстка недель 2-3 (Flexbox, Grid, анимации) и весь JavaScript с недели 4 будут либо сохранять, либо ломать доступность, заложенную сегодня. Модальные окна, кастомные дропдауны, drag-and-drop на JS — везде придётся explicitly управлять фокусом и ARIA-атрибутами, и без сегодняшней базы POUR эти темы будут восприниматься как произвольный список правил, а не система.

      +

      Конкретный пример: кастомная кнопка <div onclick="...">Отправить</div> выглядит как кнопка, но не получает фокус по Tab, не реагирует на Enter/Space и не объявляется скринридером как кнопка — три уровня доступности сломаны одним неверным выбором тега. <button>Отправить</button> даёт всё это бесплатно, без единой строчки ARIA.

      +

      Частое заблуждение — думать, что ARIA-атрибуты «чинят» доступность любого элемента. role="button" на div сообщает скринридеру, что это кнопка, но не добавляет фокусируемость и обработку клавиатуры — это придётся программировать вручную на JS. Отсюда и «первое правило ARIA»: нативный button уже умеет всё это сам.

      +

      Ключевая мысль: если страницу нельзя пройти Tab-ом — она недоступна, даже с идеальным дизайном; сегодняшний аудит A11Y.md — тренировка смотреть на свою вёрстку глазами другого пользователя.

      Читать: - web.dev: Learn Accessibility — POUR: Perceivable, Operable, Understandable, Robust

      Практика (полный трек)

      @@ -381,7 +407,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

      Git

      git add week-01/
       git commit -m "week 01 day 6: accessibility fixes and A11Y audit doc"
      @@ -390,14 +416,18 @@ 

      Git


      День 7 (Sun): Таблицы, метаданные, проект недели

      -

      Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Portfolio Landing

      Теория

      HTML-таблицы предназначены для табличных данных — расписания, сравнения, статистики. В 1990-х ими верстали макеты целых сайтов; сегодня для layout есть CSS Grid и Flexbox, а таблица для вёрстки — антипаттерн: скринридер зачитывает «строка 3, столбец 2» там, где пользователь ждёт заголовок статьи. Правильная таблица: caption (заголовок), thead с th scope="col", tbody с td. Атрибут scope связывает заголовок с колонкой или строкой.

      Метаданные в <head> влияют на то, как страницу видят извне. title — заголовок вкладки и сниппет в поиске. meta name="description" — краткое описание для Google. Open Graph-теги (og:title, og:image) управляют превью при шаринге в Telegram или LinkedIn: без них мессенджер подставит случайный текст. Favicon — иконка вкладки: link rel="icon" с PNG 32×32 или SVG для чёткости на Retina.

      -

      Ключевая мысль: таблица = данные с заголовками; для сетки страницы — CSS, не <table>.

      +

      Мысленная модель: <table> — это таблица в Excel, где каждая ячейка осмысленно связана со своей строкой и колонкой; если убрать эту связь (например, свёрстать «таблицу» через div), теряется не визуальный вид, а именно смысл — какое число к какой строке относится. Метаданные же — это витрина страницы: их не видно на самой странице, но именно по ним решают, кликать ли на ссылку в поиске или в мессенджере.

      +

      Почему это важно дальше: сегодня — последний день недели, и именно метаданные (title, description, OG-теги) часто оказываются той мелочью, которая отличает «просто сайт» от «сайта, готового к реальному использованию» — в портфолио на неделе 22 это будет заметно сразу при шаринге ссылки в чат. Таблицы вернутся при работе с данными на бэкенде (недели 11+), где то же правило «заголовок связан со значением через scope или id/headers» останется актуальным.

      +

      Конкретный пример: репост ссылки на твой learning-log в Telegram без OG-тегов покажет случайный кусок текста и, возможно, неподходящую картинку; с og:title, og:description и og:image — аккуратную карточку с твоим именем проекта и превью.

      +

      Частое заблуждение — тянуть в <table> данные, у которых на самом деле нет двух осей сравнения, просто потому что «так аккуратнее выглядит визуально». Список из одной колонки — это ul, а не таблица из одного столбца; таблица оправдана, когда данные реально пересекаются по строке и столбцу (неделя × статус, товар × цена).

      +

      Ключевая мысль: таблица = данные с заголовками; для сетки страницы — CSS, не <table>, а для видимости в поиске и мессенджерах — метаданные, а не только красивый дизайн.

      Читать: - MDN: Tablesth scope="col|row", caption

      Практика (полный трек)

      @@ -423,7 +453,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      git add week-01/
       git commit -m "week 01 day 7: tables, meta, favicon, week project complete"
      diff --git a/docs/w/02.html b/docs/w/02.html
      index 112239a..1bfa8e4 100644
      --- a/docs/w/02.html
      +++ b/docs/w/02.html
      @@ -22,15 +22,19 @@
       
       

      День 1 (Mon): Подключение CSS и селекторы

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Styled Blog Post

      Теория

      CSS (Cascading Style Sheets) отделяет оформление от структуры HTML. Подключить стили можно тремя способами: inline-атрибут style (плохо для поддержки), блок <style> в <head> (допустимо для прототипа) и внешний файл .css через <link rel="stylesheet"> — предпочтительный вариант: один файл кэшируется браузером и обслуживает все страницы сайта.

      Селектор — это «адрес» элементов, к которым применится правило. Базовые типы: по тегу (p), по классу (.card), по id (#header), по атрибуту ([type="email"]), универсальный (*). Комбинаторы уточняют связь: потомок (пробел — любой уровень вложенности), дочерний (> — только прямой ребёнок), соседний (+) и общий сосед (~). Псевдоклассы (:hover, :focus, :nth-child()) реагируют на состояние; псевдоэлементы (::before, ::after) создают виртуальные узлы — но без свойства content они не появятся на экране.

      Селектор по классу предпочтительнее #id: классы переиспользуются, id уникален и повышает специфичность, делая CSS хрупким. :not() сужает выборку элегантно: li:not(:last-child) вместо ручных классов на каждый элемент.

      -

      Ключевая мысль: внешний CSS + селекторы по классу — основа поддерживаемых стилей.

      +

      Мысленная модель: HTML прошлой недели — это здание без покраски, а CSS — маляр, который приходит и красит стены, не трогая саму конструкцию. Селекторы — это адрес: «покрась именно эти стены», и чем точнее адрес, тем меньше риск покрасить что-то лишнее по ошибке.

      +

      Почему это важно дальше: селекторы — язык, на котором ты будешь разговаривать с DOM всю оставшуюся программу. На неделе 6 в JavaScript document.querySelector('.card:not(.hidden)') использует ровно тот же синтаксис CSS-селекторов; во фреймворках (React, Vue) CSS-модули и styled-components тоже строятся вокруг классов, а не id. Плохая привычка навешивать #id на всё сегодня аукнется путаницей в компонентном коде позже.

      +

      Конкретный пример: чтобы стилизовать активный пункт меню, соблазн — дать ему id="active". Но если пункт меняется в зависимости от страницы (через JS или атрибут aria-current="page"), гораздо гибче написать .nav-link[aria-current="page"] — один селектор работает на любой странице сайта без дублирования id.

      +

      Частое заблуждение новичков — думать, что раз id «более специфичный», значит «более правильный» выбор по умолчанию. На деле высокая специфичность id — это недостаток, а не достоинство: она мешает переопределить стиль позже без !important. Правильная стратегия — начинать с классов и повышать специфичность только когда есть явная причина.

      +

      Ключевая мысль: внешний CSS + селекторы по классу — основа поддерживаемых стилей, и сегодняшняя практика с :hover/:focus-visible/:nth-child() — это тренировка думать в терминах «состояние + класс», а не «id под каждый частный случай».

      Читать: - MDN: CSS first steps — inline, <style>, внешний файл

      Практика (полный трек)

      @@ -65,15 +69,19 @@

      Git

      День 2 (Tue): Каскад, специфичность и наследование

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Styled Blog Post

      Теория

      Слово «каскад» в CSS — ключ к пониманию, почему одно свойство иногда «не работает». Когда несколько правил нацелены на один элемент, браузер выбирает победителя в три этапа: важность (!important), специфичность селектора, порядок в файле (последний при равной специфичности). Специфичность считается как веса: inline-стиль > id > class/атрибут/псевдокласс > элемент/псевдоэлемент. Цепочка #nav .item a:hover тяжелее, чем .link — и перебьёт его, даже если написана раньше.

      Наследование распространяет некоторые свойства от родителя к детям: color, font-family, line-height. Другие — margin, padding, border — не наследуются; каждый элемент начинает с нуля. Задай font-family на body, и весь текст унаследует шрифт. Ключевые слова inherit, initial, unset и revert управляют этим явно: inherit берёт значение родителя, initial — дефолт спецификации, revert — стиль браузера по умолчанию.

      Высокая специфичность — ловушка: добавить новое правило становится сложно без !important, а это запускает «войну важности». Цель — писать селекторы минимальной достаточной силы, обычно на уровне одного-двух классов.

      -

      Ключевая мысль: каскад — не баг, а механизм разрешения конфликтов; специфичность — его валюта.

      +

      Мысленная модель: каскад — это не хаос, а суд с чётким регламентом. Три этапа разрешения конфликта (важность → специфичность → порядок) — это последовательность вопросов судьи: сначала «есть ли !important?», потом «чей селектор точнее?», и только при ничьей — «кто выступил последним?». Если понимать эту последовательность, «CSS не работает» перестаёт быть загадкой и превращается в задачу с однозначным ответом.

      +

      Почему это важно дальше: специфичность и каскад будут влиять на любой CSS до конца обучения — и на неделе 3 с Flexbox/Grid, и в CSS-модулях React, и при подключении сторонних библиотек (Bootstrap, Tailwind), стили которых нужно будет переопределять осознанно, а не случайным !important. Чем раньше выработается привычка вычислять специфичность в уме, тем меньше часов будет потрачено на отладку «почему стиль не применяется» в будущем.

      +

      Конкретный пример: .button { color: blue; } и #submit-btn { color: red; } конкурируют за один и тот же элемент — при равном порядке победит id-селектор просто в силу более высокого веса, даже если правило с классом идёт ниже в файле. Добавление к кнопке класса .button--primary { color: green; } тоже проиграет id, пока специфичность id не будет снижена или селектор класса не станет точнее.

      +

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

      +

      Ключевая мысль: каскад — не баг, а механизм разрешения конфликтов; специфичность — его валюта, и сегодняшняя практика с ручным вычислением специфичности трёх селекторов — тренировка читать эту «валюту» без обращения к DevTools.

      Читать: - MDN: Cascade and inheritance

      Практика (полный трек)

      @@ -101,7 +109,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 02 day 2: cascade and specificity"
      • @@ -114,15 +122,19 @@

        Ловушки

      День 3 (Wed): Box Model

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Styled Blog Post

      Теория

      Каждый HTML-элемент в CSS — прямоугольная коробка. Боксовая модель описывает её слои, изнутри наружу: content (текст и картинки) → padding (внутренний отступ) → border (рамка) → margin (внешний отступ до соседей). Представь подарочную коробку: содержимое, мягкая подложка, обёртка и расстояние до других коробок на полке.

      По умолчанию box-sizing: content-box: свойства width и height задают только content, а padding и border добавляются сверху. Карточка width: 300px с padding: 20px и border: 2px займёт 344px — сюрприз для сетки. Глобальный сброс box-sizing: border-box включает padding и border в заявленную ширину — предсказуемая вёрстка.

      Margin collapse — особенность блочной вёрстки: вертикальные margin соседних блоков схлопываются в один (больший), а не складываются. Два блока с margin-bottom: 30px и margin-top: 20px разойдутся на 30px, не на 50. Горизонтальные margin не схлопываются. display: inline элементы игнорируют width/height; для кнопок и бейджей чаще нужен inline-block.

      -

      Ключевая мысль: border-box + понимание margin collapse = контроль над размерами без магии.

      +

      Абсолютно каждый элемент на странице — прямоугольник, даже если визуально выглядит круглым или невидимым; это стоит держать в голове как базовый факт CSS-мышления. Умение «включить» в голове границы коробок вокруг любого элемента страницы — по сути, главный навык отладки вёрстки, который пригодится до конца обучения: в DevTools эта модель визуализируется буквально теми же четырьмя слоями.

      +

      Почему это критично дальше: на неделе 3 Flexbox и Grid распределяют именно эти коробки по осям — без понимания, где заканчивается content и начинается margin, предсказать поведение сетки невозможно. Разработчики годами спорят о content-box vs border-box именно потому, что путаница в размерах — причина большинства «съехавших» макетов.

      +

      Конкретный пример: три карточки в ряд по width: 33.33% с content-box и padding: 20px каждая окажутся шире контейнера в сумме и перенесутся на новую строку — визуально «сетка сломалась» без единой ошибки в разметке. С border-box та же конструкция работает как ожидается, потому что padding вычитается из заявленных 33.33%, а не добавляется поверх.

      +

      Частое заблуждение новичков — путать margin collapse с багом браузера, когда два блока с суммарными отступами 50px визуально расходятся только на 30px. Это ожидаемое поведение спецификации CSS для смежных вертикальных margin блочных элементов — оно не работает для padding, border, горизонтальных margin или элементов с display: flex/grid в качестве родителя.

      +

      Ключевая мысль: border-box + понимание margin collapse = контроль над размерами без магии, а не жонглирование случайными пикселями до тех пор, пока «не встанет на место».

      Читать: - MDN: Box model

      Практика (полный трек)

      @@ -150,22 +162,26 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

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

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 02 day 3: box model and cards"

      День 4 (Thu): Типографика и текст

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Styled Blog Post

      Теория

      Типографика — 90% того, что пользователь читает на сайте. Шрифт задаётся стеком font-family: 'Inter', system-ui, sans-serif — браузер берёт первый доступный. font-size и font-weight строят иерархию заголовков; line-height (межстрочный интервал) критичен для комфорта: для body-текста 1.5–1.7 — золотая середина.

      Длина строки влияет на читаемость сильнее, чем кажется. Оптимум — 45–75 символов; длинные строки заставляют глаз терять начало следующей. Ограничь текст max-width: 65ch — единица ch равна ширине символа «0» текущего шрифта. Веб-шрифты подключают через @font-face или сервисы вроде Google Fonts; font-display: swap показывает системный шрифт, пока кастомный грузится — меньше «невидимого текста» (FOIT).

      Вертикальный ритм — согласованные отступы, кратные line-height. Если базовый интервал 1.6 × 16px = 25.6px, отступы между абзацами логично делать кратными этому значению. Свойства letter-spacing, text-transform и text-decoration — тонкая настройка, не злоупотребляй: уменьшенный letter-spacing на мобильном ухудшает читаемость.

      -

      Ключевая мысль: типографика — не украшение, а инженерия читаемости; ch и line-height важнее декоративных шрифтов.

      +

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

      +

      Почему это важно дальше: типографика — тот редкий навык CSS, который напрямую конвертируется в конверсию и удержание пользователей на реальных проектах; на неделе 3 при вёрстке SaaS-лендинга и позже в любых проектах именно читаемость текста будет определять, дочитает ли посетитель страницу до кнопки CTA или уйдёт раньше. Плохая типографика не «ломает» сайт визуально, но незаметно снижает эффективность всего остального дизайна.

      +

      Конкретный пример: одна и та же статья с line-height: 1.2 и max-width: 100% (растянутая на весь экран 1920px) читается тяжело — строка в 200+ символов заставляет глаз «терять» начало следующей строки при возврате. Та же статья с line-height: 1.6 и max-width: 65ch превращается в комфортный блок текста, похожий на хорошо свёрстанную книгу.

      +

      Частое заблуждение новичков — подбирать line-height и размеры «на глаз, пока не станет красиво», не привязываясь к базовому масштабу. Без системы (например, кратности вертикального ритма) отступы между разными блоками страницы начинают визуально не совпадать друг с другом, даже если каждый по отдельности выглядит нормально.

      +

      Ключевая мысль: типографика — не украшение, а инженерия читаемости; ch и line-height важнее декоративных шрифтов, а сегодняшняя практика с ограничением ширины текста в 65ch — первый шаг к этой дисциплине.

      Читать: - MDN: Typography - web.dev: Learn Typography — вертикальный ритм

      @@ -194,22 +210,26 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 02 day 4: typography and fonts"

      День 5 (Fri): Цвета, фоны и тени

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Styled Blog Post

      Теория

      Цвет в CSS — не только эстетика, но и доступность. Форматы: hex (#3366cc), rgb(), hsl(), современный oklch(). HSL и OKLCH удобны для вариаций: меняешь только lightness, сохраняя оттенок — получаешь палитру hover/active из одного базового цвета.

      Фоны выходят за сплошную заливку: background-image с linear-gradient создаёт hero-секции без тяжёлых картинок; background-size: cover масштабирует изображение на весь блок. Тени (box-shadow) и скругления (border-radius) добавляют глубину карточкам. Важный нюанс: opacity: 0.5 на родителе делает полупрозрачными всех детей; для полупрозрачного фона без влияния на текст используй rgba() или hsla().

      box-shadow рисует тень прямоугольника элемента; filter: drop-shadow() следует за альфа-каналом PNG — лучше для иконок с прозрачностью. Всегда проверяй контраст текста на фоне: WCAG AA требует 4.5:1 для обычного текста, иначе градиент «съедает» читаемость.

      -

      Ключевая мысль: rgba для полупрозрачного фона, opacity — когда прозрачным должен быть весь блок целиком.

      +

      Мысленная модель: думай о цвете не как о наборе разрозненных hex-кодов, а как о палитре с системой — базовый оттенок и его вариации по яркости, как краски художника, смешанные из одной тюбика с добавлением белого или чёрного. HSL/OKLCH делают эту систему явной в коде: меняя только один параметр (lightness), получаешь согласованный набор состояний вместо угадывания «какой ещё синий взять для hover».

      +

      Почему это важно дальше: завтра, в день 6, ты вынесешь именно эти цвета в CSS-переменные — и то, насколько системно они организованы сегодня (базовый + вариации, а не 15 несвязанных hex-кодов), определит, насколько легко будет собрать тёмную тему завтра. Хаотичная палитра сегодня означает мучительный рефакторинг завтра.

      +

      Конкретный пример: hero-секция с background: linear-gradient(135deg, #1a1a2e, #16213e) и белым текстом поверх может визуально понравиться, но если не проверить контраст в месте, где текст пересекает более светлую часть градиента, там текст может провалиться ниже 4.5:1 — форматально «одна и та же секция» в разных точках имеет разный контраст.

      +

      Частое заблуждение — считать opacity универсальным способом сделать элемент «полупрозрачным». opacity: 0.5 на карточке с текстом сделает бледным и текст, и рамку, и фон одновременно — а часто нужно затемнить только фон, оставив текст чётким. Для этого — rgba()/hsla() именно на свойстве background, а не opacity на всём блоке.

      +

      Ключевая мысль: rgba для полупрозрачного фона, opacity — когда прозрачным должен быть весь блок целиком, а системная палитра сегодня — фундамент для темизации завтра.

      Читать: - MDN color

      Практика (полный трек)

      @@ -244,15 +264,19 @@

      Git

      День 6 (Sat): CSS-переменные (Custom Properties)

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Styled Blog Post

      Теория

      CSS Custom Properties (переменные) — нативный механизм темизации без препроцессоров. Объявляются с двойным дефисом: --color-primary: #3366cc, обычно в :root (псевдокласс корня документа). Используются через var(--color-primary, #000) — второй аргумент fallback на случай отсутствия переменной.

      Главное отличие от Sass $variables: CSS-переменные живут в runtime. Их можно менять через JavaScript (element.style.setProperty), media queries и классы на html. Переменные наследуются по DOM: задай токены в :root, переопредели в .theme-dark — все дочерние элементы подхватят новые значения. Тёмная тема через переопределение токенов чище, чем дублирование сотен правил.

      Design tokens — именованные константы дизайн-системы: --spacing-md, --radius-lg, --color-text. Один источник правды: дизайнер меняет токен — обновляется весь интерфейс. Это мост между дизайном в Figma и кодом.

      -

      Ключевая мысль: CSS-переменные — живые токены, которые наследуются и меняются в runtime.

      +

      Мысленная модель: CSS-переменные — это розетки в доме, а не проводка внутри стен. Sass-переменная ($primary) — это провод, впаянный намертво при компиляции: изменить его после сборки нельзя, не пересобрав весь дом заново. CSS custom property — это розетка: воткнул другую «вилку» значения через класс или JS в любой момент, и всё, что подключено к этой розетке, сразу получает новое напряжение — без пересборки.

      +

      Почему это критично дальше: тема с переключением light/dark, персонализация интерфейса, адаптация под системные настройки пользователя (prefers-color-scheme) — всё это опирается именно на runtime-природу custom properties. На неделях с React/Vue дизайн-токены станут ещё важнее: компонентные библиотеки (MUI, Chakra) построены вокруг похожей идеи именованных токенов, а не разбросанных значений.

      +

      Конкретный пример: без переменных тёмная тема потребовала бы продублировать каждое правило с цветом (.card { background: white }.dark .card { background: #222 } для каждого компонента). С токенами достаточно переопределить --bg-surface и --text-primary один раз в .theme-dark, и все компоненты, которые уже используют var(--bg-surface), автоматически подхватят новые значения.

      +

      Частое заблуждение — путать CSS custom properties с препроцессорными переменными и ожидать, что var() можно использовать в местах, где нужно значение на этапе компиляции (например, в имени media query или в селекторе) — CSS-переменные работают только там, где ожидается значение свойства, и не подставляются в структуру самого правила.

      +

      Ключевая мысль: CSS-переменные — живые токены, которые наследуются и меняются в runtime, и именно поэтому они, а не hex-коды в каждом правиле, — правильный фундамент дизайн-системы.

      Читать: - MDN: Using CSS custom properties

      Практика (полный трек)

      @@ -280,22 +304,26 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 02 day 6: css custom properties"

      День 7 (Sun): Единицы измерения и финальная стилизация

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Styled Blog Post

      Теория

      Единицы измерения в CSS делятся на абсолютные и относительные. px — фиксированный пиксель, предсказуем, но не масштабируется с настройками пользователя. rem привязан к font-size элемента html (обычно 16px): 1.5rem = 24px при базе 16. Измени font-size на html — весь интерфейс пропорционально вырастет. em привязан к font-size родителя — во вложенных элементах может неожиданно «раздуваться».

      % — доля от родителя; vw/vh — процент viewport; ch — ширина символа «0», идеален для max-width текстовых колонок. Функция clamp(min, preferred, max) даёт fluid typography без media queries: clamp(1.5rem, 4vw, 3rem) — заголовок плавно растёт между мобильным и десктопом.

      Правило: font-size и spacing — в rem; em — для локальных отступов относительно компонента (padding кнопки); px — для тонких границ (border: 1px).

      -

      Ключевая мысль: rem для масштабируемости, clamp() для плавной адаптивности без десятка breakpoints.

      +

      Мысленная модель: px — это линейка с фиксированной длиной, rem — это линейка, которая растягивается или сжимается вместе с базовыми настройками устройства. Пользователь с ослабленным зрением, увеличивший размер шрифта в настройках браузера до 20px, увидит пропорционально увеличенный интерфейс на rem-based вёрстке — и «сломанный», не увеличивающийся текст на px-based.

      +

      Почему это важно дальше: неделя 3 целиком построена на адаптивности через Flexbox, Grid и clamp() — без уверенного понимания rem vs em vs vw сегодня, попытки построить fluid-дизайн завтра превратятся в подбор чисел методом тыка. Это последний день недели 2 — именно сегодняшняя финальная стилизация проверяет, насколько цельно всё сложилось: токены, типографика, box model, единицы.

      +

      Конкретный пример: padding: 1em на кнопке с font-size: 1.2rem внутри карточки с увеличенным текстом даст больший отступ, чем такая же кнопка в обычном месте страницы — потому что em считается от текущего, а не корневого размера шрифта. Это иногда используют осознанно (отступы масштабируются вместе с текстом компонента), а иногда — источник необъяснимого «съехавшего» паддинга.

      +

      Частое заблуждение — считать vw универсальной заменой rem для адаптивного текста. Чистый font-size: 4vw без clamp() на очень широких экранах (4K-мониторы) может дать нечитаемо огромный текст, а на очень узких — нечитаемо мелкий: vw без ограничителей масштабируется линейно и бесконечно, что и решает clamp(min, preferred, max), задавая границы разумного диапазона.

      +

      Ключевая мысль: rem для масштабируемости, clamp() для плавной адаптивности без десятка breakpoints — и то, и другое станет рабочим инструментом уже завтра, на первом дне недели про Flexbox.

      Читать: - MDN: CSS values and units

      Практика (полный трек)

      @@ -323,7 +351,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

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

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 02 day 7: rem clamp final styling"
      • diff --git a/docs/w/03.html b/docs/w/03.html index e2c0a0d..093eb4f 100644 --- a/docs/w/03.html +++ b/docs/w/03.html @@ -22,15 +22,19 @@

        День 1 (Mon): Flexbox — основы

        -

        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
        -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
        +

        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
        +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
        Связь с проектом: шаг к SaaS Landing

        Теория

        Flexbox (Flexible Box Layout) решает задачу одномерного выравнивания: элементы в ряд или в колонку. Контейнер с display: flex становится flex-контейнером; прямые дети — flex-элементами. flex-direction задаёт главную ось: row (горизонталь, по умолчанию) или column (вертикаль). justify-content выравнивает по главной оси (space-between, center); align-items — по поперечной. Свойство gap заменяет margin-хаки между элементами — чище и предсказуемее.

        У flex-элементов три рычага размера: flex-grow (как делить свободное место), flex-shrink (как сжиматься) и flex-basis (начальный размер). Сокращение flex: 1 означает flex: 1 1 0% — элемент жадно забирает доступное пространство. По умолчанию align-items: stretch растягивает детей по поперечной оси — карточки в ряду получают одинаковую высоту без фиксированного height.

        Flexbox — не замена Grid: он идеален для навигации, тулбаров, центрирования, рядов карточек. Двумерные макеты — задача Grid.

        -

        Ключевая мысль: Flexbox — одна ось, три свойства выравнивания; gap вместо margin между элементами.

        +

        После двух недель, где элементы просто «текли» друг за другом по умолчанию (block/inline), Flexbox — первый инструмент, который даёт настоящий контроль над расположением. Мысленная модель: представь, что flex-контейнер — это одна полка, а justify-content/align-items — это то, как расставлены предметы вдоль и поперёк этой полки. Главная ось — направление, куда «течёт» полка (row или column), поперечная — перпендикулярное направление.

        +

        Почему это важно дальше: до сегодняшнего дня центрирование блока по вертикали требовало хаков (position: absolute + transform, или магические margin); одна строчка display: flex; align-items: center; justify-content: center решает это раз и навсегда, и этот паттерн будет использоваться в каждом следующем проекте маршрута — от карточек товаров до модальных окон с JavaScript.

        +

        Конкретный пример: шапка сайта с логотипом слева и меню справа раньше делалась через float: left/right с последующим clearfix-хаком для родителя — хрупкая и неочевидная конструкция. С Flexbox это display: flex; justify-content: space-between на родителе — два ребёнка автоматически расходятся по краям без единого float.

        +

        Частое заблуждение новичков — пытаться решить любую задачу вёрстки Flexbox-ом, включая двумерные сетки (несколько строк и колонок одновременно, которые должны выравниваться друг относительно друга). Flexbox отлично тянет одну ось, но при попытке выстроить сложную сетку карточек с выравниванием и по строкам, и по колонкам одновременно он начинает требовать обходных путей — для этого на этой же неделе есть Grid.

        +

        Ключевая мысль: Flexbox — одна ось, три свойства выравнивания; gap вместо margin между элементами, и сегодняшняя практика с шапкой и рядом карточек — это как раз тот повседневный паттерн, который встретится в 90% проектов впереди.

        Читать: - MDN: Flexbox

        Практика (полный трек)

        @@ -65,15 +69,19 @@

        Git

      День 2 (Tue): Flexbox — практические паттерны

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к SaaS Landing

      Теория

      На практике Flexbox решает повторяющиеся паттерны. Sticky footer: body { min-height: 100vh; display: flex; flex-direction: column } и main { flex: 1 } — основной контент растягивается, подвал прижат к низу viewport даже на короткой странице. Кнопка внизу карточки: flex-column на карточке + margin-top: auto на кнопке — она уезжает вниз, текст выше занимает сколько нужно.

      Разница flex: 1 1 auto и flex: 1 1 0: первый стартует с естественного размера контента, второй — с нуля и делит место поровну. Ловушка: flex-элемент с длинным текстом не сжимается без min-width: 0 — браузер считает минимальный размер по контенту и ломает ряд.

      order и align-self меняют визуальный порядок и выравнивание отдельного элемента — используй редко. order не меняет tab-order для клавиатуры — риск для доступности.

      -

      Ключевая мысль: margin-top: auto — flex-паттерн «прижать к краю»; min-width: 0 — страховка от переполнения.

      +

      Мысленная модель для сегодняшних паттернов: margin: auto внутри flex-контейнера — это «пружина», которая заполняет всё доступное свободное пространство в указанном направлении, отталкивая элемент к противоположному краю. margin-top: auto толкает элемент вниз, margin-left: auto — вправо. Это не магия, а логичное следствие того, как flexbox распределяет свободное место между элементами.

      +

      Почему это важно дальше: карточки товаров, карточки блога, панели с кнопками действий внизу — универсальный паттерн, который повторится в SaaS-лендинге этой недели, а затем в любом React/Vue-компоненте с карточкой. Разобравшись сегодня, что «прижать к низу» — это margin-top: auto, а не фиксированная высота с абсолютным позиционированием, ты решаешь один и тот же класс задач один раз навсегда.

      +

      Конкретный пример: карточка товара с описанием разной длины — у одного товара одно предложение, у другого — три. Без margin-top: auto на кнопке «Купить», кнопки окажутся на разной высоте в ряду карточек, что выглядит неаккуратно. С этим свойством все кнопки выравниваются по нижнему краю независимо от длины текста выше.

      +

      Частое заблуждение — думать, что flex: 1 всегда даёт элементам одинаковую ширину. Если у элементов разный текстовый контент и не задан явный flex-basis: 0, браузер учитывает содержимое при расчёте начального размера — flex: 1 1 auto (значение по умолчанию flex: 1, если задавать по частям, требует внимания) может дать неравные ширины, тогда как flex: 1 1 0% гарантированно делит место поровну независимо от контента.

      +

      Ключевая мысль: margin-top: auto — flex-паттерн «прижать к краю»; min-width: 0 — страховка от переполнения, и оба паттерна сегодня в практике встретятся напрямую в карточке товара и sticky footer.

      Читать: - CSS Tricks: Flexbox Guide

      Практика (полный трек)

      @@ -101,7 +109,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 03 day 2: flexbox patterns"
      • @@ -114,15 +122,19 @@

        Ловушки

      День 3 (Wed): CSS Grid — основы

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к SaaS Landing

      Теория

      CSS Grid — двумерная сетка: строки и колонки одновременно. display: grid на контейнере; grid-template-columns и grid-template-rows задают треки. Единица fr (fraction) делит свободное пространство пропорционально: 1fr 2fr — вторая колонка вдвое шире. repeat(3, 1fr) — три равные колонки; minmax(200px, 1fr) — колонка не уже 200px, но растёт.

      Элементы позиционируются через grid-column, grid-row или именованные зоны grid-template-areas. Areas превращают CSS в карту макета: header header / sidebar main / footer footer — читаемо без подсчёта линий. grid-column: span 2 растягивает элемент на две ячейки.

      Grid vs Flex: grid для страничных макетов, галерей, дашбордов; flex для навигации, рядов кнопок, выравнивания внутри ячейки grid. Часто они работают вместе: grid — скелет страницы, flex — внутри карточки.

      -

      Ключевая мысль: Grid — две оси и именованные зоны; fr делит пространство, а не проценты от неизвестной ширины.

      +

      Мысленная модель: если Flexbox — это одна полка, то Grid — это стеллаж целиком, где ты заранее рисуешь чертёж (сколько полок, какой ширины каждая колонка) и потом расставляешь предметы по конкретным ячейкам этого чертежа. grid-template-areas буквально позволяет нарисовать этот чертёж текстом прямо в CSS — читая код, сразу видно макет страницы, не держа его в голове.

      +

      Почему это критично дальше: практически любой реальный сайт — дашборд, интернет-магазин, лендинг — имеет двумерную структуру (шапка на всю ширину, сайдбар и контент рядом, футер снизу), и Grid решает это без единого хака с float или absolute-позиционированием, которые использовались до 2017 года. Это последний крупный layout-инструмент CSS перед тем, как на следующей неделе начнётся JavaScript — Grid и Flex вместе закрывают всю вёрстку, которая понадобится дальше.

      +

      Конкретный пример: макет «шапка на всю ширину, слева сайдбар 250px, справа контент, снизу футер на всю ширину» через grid-template-areas: "header header" "sidebar main" "footer footer" с grid-template-columns: 250px 1fr — четыре строки CSS вместо десятков строк с float, clear и magic numbers, которые использовались в вёрстке 2010-х годов.

      +

      Частое заблуждение — думать, что раз Grid двумерный, значит он всегда «лучше» Flexbox и должен использоваться везде. Для одномерных задач (ряд кнопок, центрирование одного блока) Grid избыточен и требует больше кода для того же результата — правило простое: одна ось — Flexbox, две оси одновременно — Grid.

      +

      Ключевая мысль: Grid — две оси и именованные зоны; fr делит пространство, а не проценты от неизвестной ширины, и сегодняшняя практика с areas — тренировка «рисовать» макет прямо в CSS, а не вычислять его на бумаге отдельно.

      Читать: - MDN: Grid Layout

      Практика (полный трек)

      @@ -150,22 +162,26 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

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

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 03 day 3: css grid basics"

      День 4 (Thu): Grid — продвинутые макеты

      -

      Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к SaaS Landing

      Теория

      Продвинутый Grid убирает необходимость в десятках media queries. repeat(auto-fill, minmax(250px, 1fr)) создаёт responsive-сетку: браузер сам считает, сколько колонок влезет. auto-fill оставляет пустые треки, auto-fit схлопывает их — на широком экране карточки растягиваются, а не остаётся пустая колонка.

      Grid stacking — два элемента в одной ячейке: наложи текст на изображение, задав обоим grid-row: 1; grid-column: 1. Subgrid (где поддерживается) выравнивает вложенные сетки с родительской — карточки в ряду получают согласованные строки заголовков.

      Правило выбора: 1D → flex, 2D → grid. Навигация и кнопки — flex; pricing table, features grid, dashboard — grid. Вложенный grid внутри main — sidebar фиксированной ширины, контент на 1fr.

      -

      Ключевая мысль: auto-fill/auto-fit + minmax() — адаптивная сетка без ручных breakpoints.

      +

      Мысленная модель: auto-fill/auto-fit с minmax() — это не набор фиксированных breakpoint'ов «на 3 колонки при 1024px», а формула, которая пересчитывается на каждый пиксель ширины экрана. Вместо того чтобы перечислять устройства (телефон, планшет, десктоп), ты описываешь правило «сколько минимум места нужно карточке» — и браузер сам решает, сколько карточек влезет в ряд на любом экране, включая устройства, которые ещё не существуют.

      +

      Почему это важно дальше: на завтрашнем дне про адаптивный дизайн ты будешь совмещать этот подход с явными breakpoints через @media — но там, где формула auto-fill/minmax() покрывает задачу, лишний media query не нужен. Это экономит десятки строк CSS в каждом следующем проекте и делает интерфейс устойчивым к нестандартным размерам экрана без дополнительных правок.

      +

      Конкретный пример: галерея из 7 карточек с grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)) покажет 5 колонок на экране 1200px и автоматически перестроится в 2 колонки на 500px — без единой строчки @media, просто потому что при 500px помещается только 2 колонки по 200px+.

      +

      Частое заблуждение — путать auto-fill и auto-fit, думая что они одинаковы. Разница проявляется только когда элементов меньше, чем может поместиться колонок: auto-fill сохранит пустые невидимые треки (карточки останутся у левого края, не растягиваясь), а auto-fit схлопнет пустые треки и растянет существующие карточки на всю доступную ширину.

      +

      Ключевая мысль: auto-fill/auto-fit + minmax() — адаптивная сетка без ручных breakpoints, и разница между ними стоит того, чтобы проверить её сегодня на практике вживую, а не запоминать теоретически.

      Читать: - CSS Tricks: Grid Guide

      Практика (полный трек)

      @@ -193,22 +209,26 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 03 day 4: advanced grid layouts"

      День 5 (Fri): Адаптивный дизайн

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к SaaS Landing

      Теория

      Адаптивный дизайн — не «версия для мобильного», а один интерфейс, плавно подстраивающийся под экран. Подход mobile-first: базовые стили пишутся для узкого экрана (375px), затем @media (min-width: 768px) добавляют возможности для планшета и десктопа. Расширять проще, чем «отрезать» лишнее с десктопной версии.

      Breakpoints (480, 768, 1024, 1280px) — не догма, а ориентиры. Breakpoint выбирай там, где ломается контент: навигация не влезает, карточки сжимаются нечитаемо. meta viewport в <head> обязателен: без него мобильный браузер покажет «уменьшенный десктоп».

      Относительные единицы (rem, %, vw) и max-width: 100% на изображениях предотвращают горизонтальный скролл. Touch targets на мобильном — минимум 44×44px: пальцу нужна площадь больше, чем точке курсора. Container queries (@container) — следующий уровень: стили от размера контейнера, а не viewport.

      -

      Ключевая мысль: mobile-first + breakpoint по поломке контента, не по модели телефона.

      +

      Мысленная модель mobile-first: представь, что пишешь стили для самого маленького и ограниченного устройства, а затем — по мере роста экрана — добавляешь возможности, как открываешь дополнительные комнаты в доме по мере роста семьи. Desktop-first работает наоборот: сначала строишь весь особняк, а потом судорожно «сносишь стены» media queries, пытаясь втиснуть его в маленькую квартиру — отсюда и происходит большинство «сломанных на мобильном» сайтов.

      +

      Почему это важно дальше: с недели 4+ появится реальный трафик с мобильных устройств (в среднем более половины посетителей любого сайта), а на собеседованиях адаптивность — один из первых вопросов о практическом опыте. Привычка мыслить mobile-first, заложенная сегодня, экономит часы переделок в каждом будущем проекте, где по умолчанию тянет верстать «как на своём большом мониторе».

      +

      Конкретный пример: карточка с фиксированной шириной width: 400px и padding: 40px, написанная сначала для десктопа, на экране 375px вызовет горизонтальный скролл всей страницы — придётся добавлять media query, чтобы «исправить» то, что изначально не работало. Если же сначала написать width: 100%; padding: 1rem, а на широких экранах через @media (min-width: 768px) добавить max-width: 400px, скролла не возникнет никогда.

      +

      Частое заблуждение — выбирать breakpoints по размерам конкретных моделей телефонов («iPhone — 390px, значит ставим breakpoint на 390»). Экранов существуют тысячи размеров, и привязка к конкретным устройствам устаревает с каждым новым релизом телефонов. Правильный ориентир — не устройство, а момент, когда реальный контент (текст, навигация, карточки) перестаёт помещаться корректно.

      +

      Ключевая мысль: mobile-first + breakpoint по поломке контента, не по модели телефона — и сегодняшняя практика с перепиской стилей от 375px вверх — это тренировка именно такого мышления.

      Читать: - MDN: Responsive design

      Практика (полный трек)

      @@ -243,15 +263,19 @@

      Git

      День 6 (Sat): Переходы и анимации

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к SaaS Landing

      Теория

      CSS-переходы (transition) анимируют изменение свойства от значения A к B: transition: transform 0.2s ease. Указываешь свойство, длительность, функцию времени (ease, ease-in-out, cubic-bezier). Для hover-эффектов и смены состояний — идеальный инструмент.

      @keyframes + animation — для многошаговых анимаций: появление модалки, пульсация skeleton loader, бесконечный спиннер. Переход срабатывает при смене класса; keyframes идут по расписанию независимо.

      Производительность: анимируй только transform и opacity — они обрабатываются на GPU и не вызывают reflow всей страницы. Анимация width, height, margin — дорого. Длительность UI-переходов: 150–300ms; дольше кажется тормозным. Обязательно учитывай prefers-reduced-motion: reduce — у пользователей с вестибулярными нарушениями анимации могут вызывать тошноту.

      -

      Ключевая мысль: transition для состояний, @keyframes для сцен; только transform и opacity на проде.

      +

      Мысленная модель: transition — это ответ на вопрос «как измениться из точки А в точку Б», а @keyframes — это заранее срежиссированный мини-фильм с несколькими сценами, который проигрывается независимо от того, менял ли пользователь состояние элемента. Hover на кнопке — это A → Б, поэтому transition; бесконечно пульсирующий skeleton loader не имеет «состояния Б», к которому он стремится — поэтому keyframes.

      +

      Почему это важно дальше: анимации — то, что отличает статичный сайт от «живого» продукта, и на неделе 6 с JavaScript ты будешь программно добавлять/убирать классы, запускающие эти же CSS-переходы (например, класс .open на модалке) — сегодняшнее понимание, что именно class toggling запускает transition, напрямую подготавливает к событийной модели JS.

      +

      Конкретный пример: карточка с transition: transform 0.2s ease и :hover { transform: translateY(-4px) } создаёт лёгкий эффект «приподнимания» без единой строчки JavaScript — GPU обрабатывает transform без пересчёта всей раскладки страницы, поэтому анимация остаётся плавной даже на слабых устройствах.

      +

      Частое заблуждение — анимировать width или top/left для перемещения и изменения размера элементов, потому что это «интуитивно понятнее». На деле такие анимации заставляют браузер пересчитывать позиции всех соседних элементов на каждом кадре (reflow) — на сложной странице это заметно проседает по FPS, особенно на мобильных. transform: translate() и transform: scale() визуально дают тот же результат, но обрабатываются на отдельном GPU-слое без reflow.

      +

      Ключевая мысль: transition для состояний, @keyframes для сцен; только transform и opacity на проде — и это правило особенно важно проверить в сегодняшней практике на skeleton loader, где неправильный выбор свойства для анимации сразу заметен по «дёрганности».

      Читать: - MDN: CSS transitions - MDN: CSS animations

      @@ -280,22 +304,26 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 03 day 6: transitions and animations"

      День 7 (Sun): Сборка адаптивного лендинга

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к SaaS Landing

      Теория

      Финальная сборка лендинга объединяет паттерны недели. position: sticky на шапке удерживает навигацию в viewport при скролле — без JavaScript. Работает, пока родитель не обрезает overflow. aspect-ratio: 16/9 резервирует место под медиа до загрузки — меньше layout shift (CLS), когда картинка «прыгает» и сдвигает текст.

      Мобильное меню без JS — CSS-only через checkbox hack или :target, но доступность спорна (на неделе 6 заменишь на JS с клавиатурой). Перед сдачей — чеклист: 375px, 768px, 1280px в DevTools; Lighthouse ≥ 85; реальное устройство если есть.

      Архитектура CSS: variables → layout → components → utilities. Комментируй breakpoints и grid-решения в файле — через месяц сам забудешь, почему minmax(280px, 1fr).

      -

      Ключевая мысль: sticky + aspect-ratio — два CSS-приёма, которые заменяют килобайты JS.

      +

      Сегодняшний день — не про новую теорию, а про сборку всего изученного за неделю в единый рабочий продукт, и именно это упражнение показывает, насколько прочно улеглись Flexbox, Grid, адаптив и анимации. Мысленная модель финальной сборки: variables → layout → components → utilities — это порядок, в котором строят дом: сначала фундамент и коммуникации (токены), потом несущие стены (layout на grid/flex), потом мебель и отделка (компоненты), и только в конце — мелкие штрихи вроде отдельного класса .text-center (utilities).

      +

      Почему это важно дальше: с недели 4 весь HTML/CSS фундамент считается «данностью» — фокус сместится на JavaScript, который будет управлять уже готовой вёрсткой (переключать классы, добавлять контент, обрабатывать формы). Если сегодня лендинг не собран целостно, а состоит из разрозненных экспериментов по дням, будущая работа с ним через JS будет затруднена — нельзя надёжно навешивать обработчики на структуру, которая ещё не устоялась.

      +

      Конкретный пример: position: sticky на шапке с top: 0 работает отлично, пока где-то выше по дереву DOM у родителя не стоит overflow: hidden или overflow: auto — в этом случае sticky «ломается» без явной ошибки в консоли, и разработчики тратят часы, не понимая, почему шапка вдруг перестала прилипать. Это одна из самых частых практических ловушек sticky-позиционирования.

      +

      Частое заблуждение — считать, что раз лендинг «выглядит нормально» на своём мониторе, значит адаптивность готова. Реальная проверка требует явного прогона через DevTools Device Mode на нескольких размерах и, желательно, хотя бы одного реального устройства — многие баги (например, 100vh на мобильных браузерах с адресной строкой) проявляются только в реальных условиях, а не в эмуляции.

      +

      Ключевая мысль: sticky + aspect-ratio — два CSS-приёма, которые заменяют килобайты JS, а сегодняшняя итоговая сборка — экзамен на то, что весь материал недели работает вместе, а не по отдельности в изолированных примерах.

      Читать: - MDN: position - MDN: aspect-ratio

      @@ -324,7 +352,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 03 day 7: saas landing final"
      • diff --git a/docs/w/04.html b/docs/w/04.html index 7f8b624..96a9f27 100644 --- a/docs/w/04.html +++ b/docs/w/04.html @@ -23,14 +23,18 @@

        День 1 (Mon): Git — ревизия основ + git log как инструмент

        -

        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
        -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
        +

        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
        +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
        Связь с проектом: шаг к OSS Workflow Kit

        Теория

        Перед углублением в ветки стоит закрепить фундамент: Git отслеживает три состояния каждого файла — изменён (modified), проиндексирован (staged), зафиксирован (committed). Каждый коммит получает уникальный SHA-хеш — «отпечаток» снимка. git log --oneline --graph --all показывает историю как дерево решений, а не список сохранений.

        git show <hash> раскрывает конкретный коммит: автор, дата, diff. git diff — разница между working directory и staging; git diff --staged — что войдёт в следующий коммит. Это инструменты расследования: «что я наменял и зачем?».

        Conventional Commits — соглашение об именовании: feat:, fix:, docs:, chore:. Префикс сразу говорит тип изменения; в будущем из таких сообщений автогенерируется CHANGELOG. Хорошее сообщение отвечает на вопрос «зачем», а не «что нажал».

        +

        Ментальная модель: думай о Git не как о резервном копировании, а как о фотоальбоме проекта. Каждый коммит — цельный снимок всех файлов в конкретный момент, а не список построчных правок (в этом отличие от систем контроля версий старого поколения). Staging area — «поднос», на который ты выкладываешь изменения перед тем, как вклеить их в альбом одним кадром: можно взять не все файлы, а только логически связанные.

        +

        Почему это важно дальше: уже завтра git diff и git log понадобятся при разборе конфликтов слияния, а через несколько недель, когда придётся разбираться в чужом (или своём трёхмесячной давности) коде, именно история коммитов станет главным источником контекста — не документация, а сам git log объяснит, почему код выглядит именно так.

        +

        Пример: после трёх дней работы git log --oneline может выглядеть так: a1b2c3d feat: add hero section, e4f5g6h fix: broken flex layout on mobile, i7j8k9l docs: update README. По одному этому списку — без взгляда на код — понятно, что происходило в проекте.

        +

        Частое заблуждение: новички думают, что git add уже «сохраняет» файл. На самом деле фиксирует изменения только git commit; add лишь готовит их к следующему снимку, и их легко убрать из staging через git restore --staged до коммита. Сегодняшняя практика с git log, git blame и разбором commit message опирается именно на понимание этих трёх состояний.

        Ключевая мысль: git log — дневник решений; осмысленные сообщения коммитов = документация для будущего себя.

        Читать: - Pro Git: Основы — три состояния, SHA коммитов @@ -64,14 +68,18 @@

        Git

      День 2 (Tue): Ветки, слияние и конфликты

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к OSS Workflow Kit

      Теория

      Ветка в Git — просто указатель на коммит. Создать ветку дёшево: git switch -c feature/header ответвляет от текущего состояния, и ты работаешь изолированно, не ломая main. Когда фича готова — слияние (merge) переносит изменения обратно.

      Fast-forward merge возможен, если main не получил новых коммитов с момента ответвления: указатель main просто «перепрыгнет» на конец feature-ветки. Иначе Git создаёт merge commit — коммит с двумя родителями. git merge --no-ff принудительно создаёт merge commit даже при возможности ff — сохраняет видимость ветки в истории.

      Конфликт возникает, когда одна и та же строка изменена в обеих ветках. Git вставляет маркеры <<<<<<<, =======, >>>>>>> — ты вручную выбираешь итог, git add, git commit. Конфликт — не катастрофа, а диалог между версиями. git stash временно прячет незакоммиченные правки, если нужно срочно переключить ветку.

      +

      Ментальная модель: представь ветки как параллельные черновики одного текста. main — чистовик, а feature/* — листок, на котором можно свободно экспериментировать, не боясь испортить оригинал. Merge — это не «копирование», а совмещение двух версий текста построчно: там, где правки не пересекаются, Git совмещает их автоматически; там, где обе версии тронули одну и ту же строку, он честно останавливается и просит тебя решить.

      +

      Почему это важно дальше: без уверенного понимания веток и конфликтов работа в команде (недели с PR-review, а позже — реальные проекты) превращается в страх перед git merge. Умение спокойно читать маркеры конфликта и осознанно выбирать нужную версию — навык, который используется буквально каждую неделю при слиянии Pull Request.

      +

      Пример: ты правишь style.css в feature/dark-theme, добавляя background: #111, а параллельно в main кто-то (или ты сам вчера) поменял тот же селектор на background: #222. При merge Git покажет оба варианта между маркерами — нужно решить, оставить один, объединить логику или переписать заново, а не бездумно удалить «чужой» кусок.

      +

      Частое заблуждение: многие считают конфликт признаком того, что «что-то сломалось». На деле конфликт — это Git защищает тебя от тихой потери чужих изменений; после ручного разрешения обязательно проверь работоспособность кода, а не только факт исчезновения маркеров — этим и займётся сегодняшняя практика.

      Ключевая мысль: ветка — дешёвый черновик; merge — слияние черновика с основной линией.

      Читать: - Pro Git: Ветвление

      @@ -100,7 +108,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 04 day 2: branches merge conflicts"
      • @@ -113,14 +121,18 @@

        Ловушки

      День 3 (Wed): GitHub и удалённый workflow

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к OSS Workflow Kit

      Теория

      Локальный Git — половина workflow. Remote (обычно origin на GitHub) — копия репозитория на сервере. git push публикует коммиты; git pull забирает чужие и сливает с твоими. Флаг -u при первом push связывает локальную ветку с удалённой — дальше достаточно git push.

      Pull Request — запрос на слияние ветки с описанием изменений. Даже в solo-проекте PR учит дисциплине review: ты смотришь diff глазами «чужого» разработчика до merge. Стратегии merge на GitHub: обычный merge, squash (все коммиты ветки → один), rebase. Squash даёт чистую линейную историю main.

      Issues — трекер задач: баг, улучшение, идея. Коммит с fix #12 в сообщении автоматически закрывает issue №12. Fork + upstream — паттерн open source: форкаешь чужой репозиторий, вносишь правки, открываешь PR в оригинал.

      +

      Ментальная модель: если локальный Git — личный дневник, то GitHub — общая доска, на которую дневник выкладывается для чтения другими. Remote — не «резервная копия в облаке», а отдельная полноценная копия репозитория, с которой твоя локальная версия синхронизируется через push/pull, примерно как два человека редактируют документ и по очереди обмениваются версиями.

      +

      Почему это важно дальше: привычка открывать PR даже в одиночном проекте формирует дисциплину, которая станет обязательной в командной разработке — там код почти никогда не попадает в main напрямую, а PR с описанием и review — стандартный процесс в любой компании. Issues и связка fix #12 — тот же язык, на котором ведутся реальные open-source проекты.

      +

      Пример: ты создаёшь issue «Кнопка не видна на мобильном», чинишь баг в ветке fix/mobile-button, а в сообщении коммита пишешь fix: button visibility on mobile, closes #12 — после merge issue закроется автоматически, и в истории останется прямая связь «проблема → решение».

      +

      Частое заблуждение: новички считают, что PR нужен только когда работаешь в команде. На самом деле self-review через PR-диф — это возможность увидеть свой код «со стороны» ещё до того, как он попадёт в основную ветку, и поймать баги, которые не видны в редакторе. Сегодняшняя практика с созданием репозитория, PR и issue тренирует именно этот полный цикл.

      Ключевая мысль: GitHub = remote + социальный слой; PR — разговор о коде до попадания в main.

      Читать: - GitHub: Hello World

      @@ -149,21 +161,25 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 04 day 3: github remote and PR"

      День 4 (Thu): DevTools — Elements и Console

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к OSS Workflow Kit

      Теория

      Chrome DevTools — рентген твоей страницы. Панель Elements показывает живое DOM-дерево: кликни на узел — увидишь применённые стили, box model, flex/grid overlay. Вкладка Styles перечисляет все CSS-правила с указанием файла и строки; перечёркнутое свойство проиграло в каскаде — ищи победителя выше. Computed — итоговые вычисленные значения после каскада, наследования и браузерных дефолтов.

      Live-редактирование CSS в DevTools — быстрый эксперимент: подобрал отступ — перенеси в файл. Flex/Grid overlay рисует треки и gap поверх страницы — не гадай, смотри. В Console $0 — ссылка на элемент, выбранный в Elements; мост между визуальным и программным исследованием.

      console.log — базовый вывод; console.table — таблица для массивов объектов; console.group — группировка связанных логов. Уровни warn и error выделяются визуально и фильтруются.

      +

      Ментальная модель: DevTools — не «дополнительный инструмент для продвинутых», а рентгеновский снимок твоей страницы в реальном времени. Elements показывает не исходный HTML-файл, а живой DOM — то, во что браузер превратил разметку прямо сейчас, включая изменения, сделанные JS. Это принципиально другая картина, чем «View Page Source», который показывает статичный исходник.

      +

      Почему это важно дальше: без уверенного владения Elements и Console отладка CSS и будущего JS превращается в метод «тыка» — правишь код, обновляешь страницу, смотришь, повторяешь. С DevTools ты меняешь значение прямо в браузере и мгновенно видишь результат, а находишь причину проблемы за секунды через Computed и Styles. Это основной инструмент во всех последующих неделях, включая отладку JavaScript.

      +

      Пример: элемент выглядит не так, как ожидалось — отступ слишком большой. Открываешь Elements, кликаешь на элемент, смотришь Styles: видно зачёркнутое правило margin: 0 из одного файла и победившее margin: 16px из другого, более специфичного селектора. Проблема найдена за 10 секунд, а не за 10 минут просмотра CSS-файлов.

      +

      Частое заблуждение: начинающие правят стили прямо в DevTools и считают, что «исправили баг» — но эти изменения исчезают при обновлении страницы, потому что они не сохраняются в файл. DevTools — инструмент для эксперимента и диагностики, а не для постоянного редактирования; найденное значение всегда нужно перенести в исходный CSS-файл, что и требует сегодняшняя практика.

      Ключевая мысль: Styles — «кто перебил?», Computed — «что в итоге?»; overlay — «как устроена сетка?».

      Читать: - Chrome DevTools: Overview

      @@ -192,21 +208,25 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 04 day 4: devtools elements console"

      День 5 (Fri): DevTools — Network, Sources, Performance

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к OSS Workflow Kit

      Теория

      Панель Network показывает каждый HTTP-запрос при загрузке страницы: URL, статус, размер, время. Waterfall — диаграмма «кто за кем»: видно, что блокирует рендер (тяжёлые картинки, синхронные скрипты). Статусы: 200 OK, 304 Not Modified (из кэша), 404 Not Found. При разработке включай Disable cache, иначе видишь устаревшие файлы.

      Sources — отладка JavaScript: breakpoint останавливает выполнение в точке; step over/into проходят по строкам; watch expressions следят за переменными. Performance записывает профиль: FPS, long tasks, jank при скролле. Lighthouse в DevTools — аудит Performance, Accessibility, Best Practices с конкретными рекомендациями.

      Вкладка Application — хранилища браузера: Local Storage, Cookies, Service Workers (обзор на будущее). Тяжёлый ресурс в Network — первый кандидат на оптимизацию: сжатие, WebP, lazy loading.

      +

      Ментальная модель: если Elements — это рентген структуры страницы, то Network — рентген её загрузки во времени. Waterfall буквально показывает, что происходит от нулевой миллисекунды до полной загрузки: какой запрос начался первым, какой ждал завершения другого, что можно распараллелить. Sources и Performance добавляют временное измерение к тому, что раньше казалось мгновенным «код просто выполнился».

      +

      Почему это важно дальше: на неделях с JavaScript breakpoint в Sources станет основным способом отладки — гораздо быстрее и надёжнее, чем расставлять console.log вручную. А умение читать Lighthouse-отчёт понадобится перед сдачей любого проекта курса: это стандартный внешний критерий качества, который проверяющий может запустить за 10 секунд.

      +

      Пример: страница грузится 4 секунды. Открываешь Network, видишь в waterfall один PNG весом 3 МБ, который блокирует появление остального контента. Сжимаешь его до WebP весом 200 КБ — время загрузки падает в разы, а Lighthouse Performance-score растёт на 20+ пунктов.

      +

      Частое заблуждение: новички думают, что статус 304 — это ошибка, раз число «не как 200». На самом деле 304 Not Modified означает, что браузер удачно переиспользовал кэш и не скачивал файл заново — это хороший знак производительности, а не проблема. Похожая путаница возникает и с breakpoint в Sources: кажется, что это «то же самое, что console.log, но сложнее» — на деле breakpoint замораживает выполнение целиком, позволяя изучить значения всех переменных в этой точке одновременно, а не только той, что ты решил залогировать заранее. Сегодняшняя практика с анализом waterfall и запуском Lighthouse научит отличать реальные проблемы от нормального поведения браузера.

      Ключевая мысль: Network waterfall — карта загрузки; Lighthouse — чеклист перед сдачей.

      Читать: - Chrome DevTools: Network @@ -243,14 +263,18 @@

      Git

      День 6 (Sat): Workflow разработчика

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к OSS Workflow Kit

      Теория

      Workflow — это привычки, которые масштабируются от solo до команды. GitHub Flow — простейший: main всегда deployable, каждая фича в ветке → PR → merge. Git Flow сложнее (develop, release) — избыточен для учебных проектов. Trunk-Based — короткоживущие ветки, частые merge в main — для зрелых команд с CI.

      Conventional Commits (feat:, fix:, docs:) — единый язык сообщений; из них генерируется CHANGELOG. Pre-commit checklist: git diff глазами ревьюера, нет ли .env в staging, страница открывается, Lighthouse не упал. Prettier убирает споры о форматировании — один .prettierrc на проект.

      VS Code Git panel, diff view, GitLens — ускоряют ежедневную работу. Code review — не придирка, а передача знаний: даже self-review перед push ловит опечатки и лишние файлы.

      +

      Ментальная модель: workflow — это не набор строгих правил, а привычки, которые снижают трение между «я написал код» и «код безопасно попал в основную ветку». Чем больше шагов автоматизировано (Prettier форматирует, PR-шаблон напоминает о чек-листе), тем меньше энергии тратится на рутину и тем больше остаётся на саму задачу.

      +

      Почему это важно дальше: к этому моменту у тебя уже есть Git, ветки, PR и DevTools по отдельности — сегодня они складываются в единый ежедневный ритуал. Именно такой workflow (feature-ветка → self-review → PR → merge) станет твоей рабочей нормой на всех следующих неделях и в первой работе, поэтому его стоит закрепить как автоматизм, а не разовое упражнение.

      +

      Пример: перед сегодняшним PR ты открываешь diff и видишь, что случайно закоммитил console.log('test') и файл .DS_Store. Self-review до отправки PR ловит это за 30 секунд — ревьюер (в командной работе) не тратит время на комментарий «убери debug-лог», а видит чистый, готовый к обсуждению код.

      +

      Частое заблуждение: многие считают Prettier и единый стиль коммитов «формальностью для перфекционистов». На практике споры о форматировании (табы vs пробелы, кавычки) съедают время code review впустую — автоматизация этого убирает бессмысленные дискуссии и оставляет разговор только о логике кода. Аналогично с Conventional Commits: кажется, что префикс feat:/fix: — просто украшение, но именно по нему автоматические инструменты позже соберут CHANGELOG без единой ручной правки. Сегодняшняя практика с настройкой Prettier и PR template закрепляет эту автоматизацию раз и навсегда.

      Ключевая мысль: GitHub Flow + Conventional Commits + self-review = профессиональный минимум.

      Читать: - Conventional Commits @@ -280,21 +304,25 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 04 day 6: conventional commits prettier"

      День 7 (Sun): Интеграция и практика

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к OSS Workflow Kit

      Теория

      Инструменты расследования истории: git log — хронология; git diff — разница между состояниями; git show — один коммит целиком; git blame — кто и когда изменил каждую строку файла. Blame не для поиска виноватых, а для понимания контекста: «зачем эта строка появилась?».

      Отмена изменений — два разных инструмента. git revert <hash> создаёт новый коммит, отменяющий старый — безопасно для shared main, история не переписывается. git reset --hard откатывает указатель ветки — переписывает историю; только на локальных ветках, никогда на запушенном main без согласования.

      GitHub Pages публикует статику из ветки gh-pages или через Actions — бесплатный live demo для портфолио. git clone в новую папку — тест: «смогу ли я развернуть проект с нуля?» — must-have перед сдачей.

      +

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

      +

      Почему это важно дальше: в командной работе (и в реальных проектах) reset --hard на общей ветке — одна из немногих Git-операций, которая может по-настоящему навредить чужой работе. Привычка тянуться к revert по умолчанию, а reset использовать только на приватных, ещё не запушенных ветках — защищает и тебя, и коллег. Деплой на GitHub Pages сегодня — это и финальная проверка того, что весь пройденный путь (Git → GitHub → DevTools) складывается в реальный, доступный по ссылке продукт.

      +

      Пример: ты закоммитил правку, которая сломала лендинг, и уже запушил её в main. git revert HEAD создаст новый коммит, отменяющий изменения — main снова рабочий, а история честно показывает, что было и что исправлено. Если бы ты сделал reset --hard HEAD~1 и запушил force — коллега, который уже успел стянуть сломанный коммит, оказался бы в противоречивом состоянии.

      +

      Частое заблуждение: новички считают git clone в новую папку избыточным шагом «раз всё и так работает у меня». На деле это единственный надёжный способ проверить, что в .gitignore не потерялся нужный файл и что проект действительно воспроизводим с нуля — именно это проверяет сегодняшняя практика перед финальным тегом.

      Ключевая мысль: revert — безопасная отмена; reset --hard — только локально; clone — финальный тест переносимости.

      Читать: - Pro Git: Отмена изменений @@ -324,7 +352,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 04 day 7: github pages contributing"
      • diff --git a/docs/w/05.html b/docs/w/05.html index eadf5b5..c09e23a 100644 --- a/docs/w/05.html +++ b/docs/w/05.html @@ -22,14 +22,18 @@

        День 1 (Mon): Введение и переменные

        -

        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
        -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
        +

        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
        +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
        Связь с проектом: шаг к Console Task Manager

        Теория

        JavaScript в браузере — язык, который оживляет страницу. Браузер парсит HTML, строит DOM, затем загружает и выполняет JS в основном потоке (main thread). Код идёт сверху вниз; тяжёлый цикл блокирует UI — кнопки не реагируют, пока цикл не завершится.

        Подключение: <script defer src="app.js"> — скрипт грузится параллельно с HTML и выполняется после парсинга, не блокируя рендер. type="module" — ES-модули с изолированной областью видимости и import/export. Переменные: let — изменяемая; const — нельзя переприсвоить, но объект по const можно мутировать (менять свойства). var — устарел: function scope и поднятие (hoisting) создают ловушки.

        Temporal Dead Zone (TDZ): let/const недоступны до строки объявления — ReferenceError вместо тихого undefined. Строгий режим 'use strict' ловит опечатки в именах переменных и небезопасные приёмы.

        +

        Ментальная модель: представь браузер как читателя, который сначала бегло просматривает весь файл (парсинг и «поднятие» объявлений), а только потом читает его вдумчиво сверху вниз (выполнение). var при беглом просмотре сразу создаёт переменную со значением undefined — поэтому обращение к ней до объявления не падает с ошибкой, а тихо возвращает undefined, маскируя баг. let/const в TDZ ведут себя строже: переменная «зарезервирована», но трогать её нельзя — это осознанное решение авторов языка сделать ошибки видимыми сразу.

        +

        Почему это важно дальше: от этого фундамента зависит вообще всё в JS — функции, объекты, DOM-события в следующих неделях объявляются через let/const, и понимание того, когда переменная «жива», а когда ещё нет, объясняет добрую половину загадочных багов новичков («почему тут undefined, а не моё значение»).

        +

        Пример: console.log(x); var x = 5; выведет undefined без ошибки — hoisting поднял объявление, но не присваивание. Замени на let: console.log(x); let x = 5; — получишь ReferenceError: Cannot access 'x' before initialization, потому что x в TDZ до строки объявления.

        +

        Частое заблуждение: начинающие думают, что const делает объект неизменяемым целиком. На самом деле const запрещает только переприсвоение самой переменной (user = {} — ошибка), а свойства объекта менять можно (user.age = 26 — сработает). Это первое, что стоит проверить в сегодняшней практике на шаге с мутацией const-объекта.

        Ключевая мысль: defer + let/const + strict mode — современный старт без сюрпризов hoisting.

        Читать: - learn.javascript.ru: Введение — как выполняется JS в браузере @@ -66,14 +70,18 @@

        Git

      День 2 (Tue): Типы данных и операторы

      -

      Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Console Task Manager

      Теория

      JavaScript — динамически типизированный язык: тип определяется значением, а не объявлением. Примитивыnumber, string, boolean, null, undefined, symbol, bigint — неизменяемы: str.toUpperCase() возвращает новую строку, оригинал не трогает. Всё остальное — объекты (массивы, функции, plain objects).

      typeof возвращает строку с типом; ловушка: typeof null === 'object' — исторический баг, проверяй value === null. null — намеренное «пусто»; undefined — переменная не инициализирована. Сравнение == приводит типы неявно ('5' == 5 → true); === сравнивает значение и тип — используй всегда в новом коде.

      Template literals `Привет, ${name}!` поддерживают интерполяцию и многострочность — чище конкатенации через +. Truthy/falsy: 0, '', null, undefined, NaN, false — falsy; всё остальное truthy.

      +

      Ментальная модель: думай о == как о переводчике, который сначала пытается «подогнать» два разных языка (типа) под общий знаменатель, а потом сравнивает — и этот перевод не всегда очевиден. === ничего не переводит: сравнивает как есть, тип и значение. Именно поэтому опытные разработчики почти никогда не используют == — предсказуемость важнее «экономии» одного символа.

      +

      Почему это важно дальше: динамическая типизация — источник и гибкости, и большинства багов JS. Понимание того, где JS молча приводит типы (в сравнении, в сложении, в условиях if), — фундамент для отладки на всех следующих неделях, включая работу с формами (неделя 6-7), где данные из инпутов всегда приходят строками.

      +

      Пример: '5' == 5 вернёт true, потому что == приводит строку к числу перед сравнением. Но '5' === 5 вернёт false — разные типы. Похожая ловушка: [] == false даёт true из-за цепочки неявных приведений, тогда как [] === false — однозначно false. Такие примеры стоит проверить вживую в Console, а не запоминать как правило.

      +

      Частое заблуждение: многие считают null и undefined взаимозаменяемыми синонимами «пусто». На деле undefined — это то, что даёт сам JS, когда значения ещё нет (необъявленная переменная, отсутствующее свойство объекта, функция без return), а null — то, что программист осознанно присваивает, чтобы сказать «здесь намеренно ничего нет». Различие пригодится при проектировании функций в сегодняшней практике.

      Ключевая мысль: === вместо ==; примитивы неизменяемы; nullundefined по смыслу.

      Читать: - learn.javascript.ru: Типы — примитивы и объекты @@ -103,7 +111,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 05 day 2: types and operators"
      • @@ -116,14 +124,18 @@

        Ловушки

      День 3 (Wed): Условия и циклы

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Console Task Manager

      Теория

      Условия направляют поток выполнения. if/else — базовая развилка; тернарный оператор условие ? a : b — для простых выборов в одну строку, не для вложенных лабиринтов. switch сравнивает значение с case; без break выполнение проваливается в следующий case — частая ошибка новичков.

      Циклы: while — пока условие true; do...while — минимум одна итерация; for — классика с счётчиком. break выходит из цикла, continue — пропускает текущую итерацию. Для массивов позже предпочтительнее for...of, но классический for нужен для индексов и обратного обхода.

      Early return в функциях уменьшает вложенность: вместо if (ok) { ... много кода }if (!ok) return; и дальше линейный код. Truthy/falsy позволяют писать if (name) вместо if (name !== '' && name !== null) — но понимай, что 0 и '' тоже falsy.

      +

      Ментальная модель: условия и циклы — это то, что превращает статичный код в программу, способную принимать решения и повторять действия. Если переменные и типы — это «существительные» языка программирования, то if, for, while — его «глаголы»: они управляют потоком выполнения, решая, какой код выполнится, а какой — нет, и сколько раз.

      +

      Почему это важно дальше: без уверенного владения циклами невозможна работа с массивами (уже завтра) и DOM-списками (неделя 6) — рендеринг списка задач в интерфейсе буквально означает «пройтись циклом по массиву и создать элемент для каждого». Early return как стиль тоже останется с тобой навсегда — это один из главных приёмов для читаемого кода в любом языке.

      +

      Пример: классическая ошибка switch без breakcase 'A': console.log('Отлично'); case 'B': console.log('Хорошо'); — при 'A' выведет оба сообщения, потому что выполнение «проваливается» в следующий case. Добавление break после каждого блока — обязательная привычка, если явно не нужен fallthrough.

      +

      Частое заблуждение: новички считают тернарный оператор «более крутой» заменой любому if/else и начинают вкладывать тернарники друг в друга (a ? b : c ? d : e) — получается код, который сложнее читать, чем обычный if. Правило простое: тернарник — для одной простой развилки в присваивании или выводе, if/else — для всего остального, включая ветвление в сегодняшнем FizzBuzz.

      Ключевая мысль: switch без break — провал; early return — меньше вложенных if.

      Читать: - learn.javascript.ru: Условное ветвление @@ -153,21 +165,25 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 05 day 3: conditions and loops"

      День 4 (Thu): Функции

      -

      Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Console Task Manager

      Теория

      Функция — именованный блок кода, который можно вызывать многократно. Declaration (function foo() {}) поднимается (hoisting) — доступна до строки объявления. Expression (const foo = function() {}) — нет. Arrow functions (const foo = () => {}) — короткий синтаксис; неявный return при () => выражение без фигурных скобок.

      Параметры и аргументы: параметры в объявлении, аргументы при вызове. Значения по умолчанию (greeting = 'Привет') и rest (...numbers) делают сигнатуру гибкой. Чистая функция — одинаковый вход всегда даёт одинаковый выход, без побочных эффектов (изменения внешних переменных, DOM, сети). Такие функции проще тестировать и переиспользовать.

      Arrow functions не имеют своего this — важно для методов объектов (неделя 6). Принцип SRP (Single Responsibility): одна функция — одна задача; calculateTotal, не doEverything.

      +

      Ментальная модель: функция — это маленькая машина: на входе параметры, внутри — чёрный ящик преобразований, на выходе — результат через return. Чистая функция не имеет «утечек» наружу: не трогает глобальные переменные, не меняет DOM, не делает сетевых запросов — только считает и возвращает. Такую машину легко тестировать отдельно от всей программы и переиспользовать где угодно.

      +

      Почему это важно дальше: буквально весь курс дальше строится на функциях — методы массивов (завтра), обработчики событий (неделя 6), запросы к API (неделя 7). Разделение на маленькие чистые функции с одной ответственностью — это ровно то, что отличает читаемый проект от «одного гигантского файла, в котором страшно что-то менять».

      +

      Пример: function addToCartAndUpdateUIAndSendAnalytics(item) {...} — это функция с тремя ответственностями сразу, её сложно тестировать и ещё сложнее переиспользовать. Разбив на addToCart(cart, item) (чистая, возвращает новый массив), renderCart(cart) (рисует DOM) и trackEvent(name) (аналитика), получаешь три независимых, понятных куска, каждый из которых можно менять не боясь сломать остальные.

      +

      Частое заблуждение: новички думают, что arrow function — это просто «более короткий синтаксис» без разницы в поведении. На деле у arrow function нет собственного this — она берёт его из внешнего контекста, что критично для методов объектов и обработчиков событий на неделе 6, где ошибка с this — одна из самых частых причин «код не работает, а ошибки нет». Ещё одна тонкость: неявный return в стрелочной функции работает только без фигурных скобок — стоит добавить {}, и return придётся писать явно, иначе функция вернёт undefined.

      Ключевая мысль: чистые функции + SRP = код, который можно читать, тестировать и переиспользовать.

      Читать: - learn.javascript.ru: Функции

      @@ -196,21 +212,25 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 05 day 4: functions and utils"

      День 5 (Fri): Массивы — основы

      -

      Время (полный): ~45м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Console Task Manager

      Теория

      Массив — упорядоченная коллекция значений с числовыми индексами (с 0). Массивы мутабельны: push/pop с конца, shift/unshift с начала. splice изменяет массив на месте (удаляет/вставляет); slice возвращает копию участка, оригинал не трогает — частая путаница новичков.

      Поиск: indexOf, includes. Spread [...arr] создаёт shallow copy — вложенные объекты остаются общими ссылками. for...of перебирает значения; for...in по массиву даёт индексы как строки — для массивов не используй.

      Свойство length можно менять вручную — массив обрежется, но это редкий приём. Модель задачи {id, title, done} в массиве — фундамент Todo-приложения.

      +

      Ментальная модель: массив удобно представлять как пронумерованный список ящиков в ряд: у каждого ящика есть номер (индекс) начиная с 0, и ты можешь взять содержимое конкретного ящика напрямую, зная номер, вместо того чтобы перебирать все по очереди. Методы push/pop/shift/unshift работают только с крайними ящиками ряда — поэтому они быстрые; вставка в середину (splice) требует сдвинуть все ящики после неё.

      +

      Почему это важно дальше: массив объектов {id, title, done} — это ровно та структура данных, вокруг которой построен весь Console Task Manager этой недели, а затем DOM Todo App на неделе 6. Понимание разницы между мутацией (splice, push) и созданием копии (slice, spread) станет критичным при работе с состоянием приложения — случайная мутация массива, который «где-то ещё используется», один из самых коварных багов в JS.

      +

      Пример: const copy = arr.slice(1, 3) возвращает новый массив с элементами с индекса 1 по 2, не трогая arr. А arr.splice(1, 2) удаляет те же элементы из самого arr и возвращает удалённые — оригинал изменится. Спутав эти методы, легко случайно испортить данные, которые нужны были дальше в неизменном виде.

      +

      Частое заблуждение: новички используют for...in для перебора массивов по аналогии с объектами. Но for...in перебирает индексы как строки и может включить лишние перечисляемые свойства, если они есть у массива — для массивов правильный выбор for...of (по значениям) или классический for (когда нужен индекс). Ещё одна ловушка: [...arr] создаёт новый массив, но если внутри лежат объекты, копируются только ссылки на них — изменение поля вложенного объекта в копии отразится и на оригинале. Сегодняшняя практика со списком покупок построена именно на for...of.

      Ключевая мысль: slice — копия без мутации; splice — мутация; for...of, не for...in.

      Читать: - learn.javascript.ru: Массивы

      @@ -246,14 +266,18 @@

      Git

      День 6 (Sat): Методы массивов

      -

      Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Console Task Manager

      Теория

      Методы массивов высокого порядка — рабочая лошадка современного JS. map трансформирует каждый элемент и возвращает новый массив. filter отбирает по условию. reduce сворачивает массив в одно значение: сумма, группировка, flatten. find / findIndex — первый подходящий элемент. some / every — проверки «хотя бы один» / «все».

      forEach выполняет действие для каждого элемента, но ничего не возвращает — для побочных эффектов (логирование). Нужен новый массив — map. Цепочки .filter().map().reduce() читаются как конвейер данных.

      Ловушка sort: без compare-функции сортирует как строки[10, 5, 40][10, 40, 5]. Для чисел: (a, b) => a - b. Мутирует исходный массив — сначала [...arr].sort().

      +

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

      +

      Почему это важно дальше: map/filter/reduce — это язык, на котором пишется современный JavaScript и особенно React (когда дойдёшь до фреймворков): рендеринг списка компонентов почти всегда начинается с .map(). Умение читать и писать цепочки этих методов вместо ручных циклов резко повышает читаемость и снижает количество багов вроде забытого break или неправильного индекса.

      +

      Пример: задача «сумма цен товаров дороже 100» императивно — это цикл с условием и накопительной переменной. Декларативно: items.filter(i => i.price > 100).reduce((sum, i) => sum + i.price, 0) — три слова описывают весь алгоритм, и почти невозможно ошибиться в границах цикла, потому что их просто нет.

      +

      Частое заблуждение: новички путают forEach с map, ожидая, что forEach тоже вернёт новый массив — но forEach всегда возвращает undefined, он предназначен только для побочных эффектов (например, логирования), а не для трансформации данных. Похожая путаница со sort: он мутирует исходный массив, поэтому если оригинал ещё нужен неотсортированным, всегда работай с копией через [...arr].sort(...). Если нужен новый массив — это всегда map, что и отрабатывается в сегодняшних задачах на фильтрацию и группировку.

      Ключевая мысль: map/filter/reduce — декларативный стиль; sort всегда с compare-функцией для чисел.

      Читать: - learn.javascript.ru: Методы массивов

      @@ -282,21 +306,25 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 05 day 6: array methods"

      День 7 (Sun): Мини-проект и закрепление

      -

      Время (полный): ~45м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Console Task Manager

      Теория

      Отладка — навык не менее важный, чем написание кода. Stack trace в Console показывает цепочку вызовов: читается снизу вверх — последний вызов (где упало) наверху. debugger в коде останавливает выполнение, если DevTools открыты — альтернатива ручному breakpoint в Sources.

      Разбиение на функции (addTask, removeTask, listTasks) и файлы упрощает отладку: сломалось удаление — смотришь одну функцию, не весь скрипт. JSDoc (@param, @returns) документирует сигнатуру — IDE подсказывает типы до перехода на TypeScript.

      Консольное Todo без DOM — чистая тренировка data layer: массив + функции. На неделе 6 тот же массив «оживят» через renderTasks().

      +

      Ментальная модель: отладка — это не «случайно наткнуться на исправление», а систематическое сужение области поиска, как игра в «горячо-холодно». Stack trace сразу указывает точное место падения и весь путь вызовов, которые к нему привели — это гораздо быстрее, чем расставлять console.log наугад по всему файлу и гадать, докуда код вообще дошёл.

      +

      Почему это важно дальше: сегодняшний Console Task Manager без DOM — намеренно упрощённая версия завтрашнего (уже на неделе 6) реального приложения: тот же массив задач и те же функции addTask/removeTask останутся, просто добавится слой отрисовки renderTasks(). Умение отлаживать чистую логику отдельно от визуального слоя — ключевой навык: баг проще искать, когда переменных, которые могут быть виноваты, вдвое меньше.

      +

      Пример: ошибка TypeError: Cannot read properties of undefined (reading 'title') в stack trace показывает точную строку и цепочку вызовов сверху вниз — читая её снизу вверх, видно: сначала вызвали listTasks(), та вызвала formatTask(task), и именно в formatTask task оказался undefined. Дальше остаётся понять, почему в массив попал пустой элемент — а не искать вслепую по всему файлу.

      +

      Частое заблуждение: новички читают текст ошибки только в первой строке и паникуют, не долистав до места в своём коде — часто первая строка указывает на встроенную функцию браузера, а причина в твоём коде находится на пару строк ниже в stack trace. Ещё одна ошибка новичков — удалять console.log сразу после того, как баг найден, вместо того чтобы оставить структурные логи или, ещё лучше, покрыть находку осмысленным именем переменной. Умение читать trace целиком, а не только заголовок, — то, что отрабатывается в сегодняшней практике с breakpoint.

      Ключевая мысль: stack trace + breakpoint > десять console.log; функции — единицы отладки.

      Читать: - Chrome DevTools: JavaScript

      @@ -325,7 +353,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 05 day 7: console todo project"
      • diff --git a/docs/w/06.html b/docs/w/06.html index a79fab7..99288d8 100644 --- a/docs/w/06.html +++ b/docs/w/06.html @@ -22,14 +22,18 @@

        День 1 (Mon): Объекты — основы

        -

        Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
        -Время (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
        +

        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
        +Время (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
        Связь с проектом: шаг к DOM Todo App

        Теория

        Объект в JavaScript — коллекция пар ключ–значение. Литерал { name: 'Анна', age: 25 } — самый частый способ создания. Доступ: точечная нотация user.name и скобочная user['name'] — вторая нужна для динамических ключей user[fieldName]. Методы — функции как свойства; внутри метода this ссылается на сам объект.

        Объекты хранятся по ссылке: const b = a копирует ссылку, не содержимое. Shallow copy через {...obj} или Object.assign — вложенные объекты остаются общими. Object.keys, values, entries — обход свойств; entries удобен для рендеринга пар в DOM.

        for...in перебирает и унаследованные свойства — для собственных используй Object.keys или hasOwnProperty. Модель task = { id, title, done } с методом toggle() — мост к Todo App.

        +

        Ментальная модель: если массив — пронумерованный ряд ящиков, то объект — картотека с именованными карточками: чтобы найти нужное значение, не важен порядок, важно имя ключа. Хранение «по ссылке» удобно представить так: переменная — это не сам ящик с вещами, а бумажка с адресом ящика. Скопировав бумажку (const b = a), ты получаешь второй адрес того же самого ящика, а не новый ящик с копией содержимого.

        +

        Почему это важно дальше: модель объекта {id, title, done} — это буквально структура данных, вокруг которой строится DOM Todo App на этой неделе и все последующие проекты курса. Понимание ссылочной природы объектов защитит от одного из самых частых источников багов в JS-приложениях — случайного изменения объекта, который используется сразу в нескольких местах программы.

        +

        Пример: const original = { count: 1 }; const copy = original; copy.count = 99; — после этого original.count тоже станет 99, потому что copy — не новый объект, а второй адрес того же самого. Чтобы получить независимую копию, нужен {...original} — но и он скопирует только верхний уровень: если внутри есть вложенный объект, он останется общим.

        +

        Частое заблуждение: новички думают, что const user = {} защищает объект от изменений, раз переменная константа. На деле const фиксирует только адрес (ссылку), а не содержимое — свойства объекта можно менять сколько угодно. Это стоит явно проверить в сегодняшней практике на шаге с shallow copy.

        Ключевая мысль: объект — словарь по ссылке; spread копирует поверхностно, не глубоко.

        Читать: - learn.javascript.ru: Объекты — литералы, свойства, методы

        @@ -65,14 +69,18 @@

        Git

      День 2 (Tue): Деструктуризация и spread для объектов

      -

      Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к DOM Todo App

      Теория

      Деструктуризация извлекает поля из объекта или элементы из массива в переменные: const { name, age } = user. Переименование: { name: userName }. Значения по умолчанию: { role = 'user' } — если поля нет. В параметрах функции printUser({ name, email }) сигнатура самодокументируется.

      Spread в объектах объединяет и переопределяет: const config = { ...defaults, ...userConfig } — поля из userConfig побеждают. Порядок важен: правый объект перекрывает левый. Rest собирает остаток: const { id, ...rest } = productrest без id, удобно перед логированием без пароля.

      Иммутабельное обновление: { ...task, done: true } — новый объект, оригинал не тронут. Паттерн для state management и React-подготовки. Swap переменных: [a, b] = [b, a] — элегантно через деструктуризацию массива.

      +

      Ментальная модель: деструктуризация — это распаковка посылки: вместо того чтобы работать с целым объектом (user.name, user.age в трёх разных местах), ты сразу «раскладываешь» нужные поля по отдельным переменным, а посылку (сам объект) можно выбросить. Spread, наоборот, — упаковка: собираешь несколько маленьких объектов в один новый, причём поля справа перекрывают поля слева, как более поздняя запись в анкете перебивает раннюю.

      +

      Почему это важно дальше: иммутабельное обновление через spread ({...task, done: true}) — это ровно тот паттерн, который лежит в основе state management в React и других фреймворках: там объекты никогда не мутируют напрямую, только заменяются новыми копиями с изменённым полем. Освоив это сейчас на простых задачах, ты избежишь одной из самых частых путаниц при переходе на фреймворки.

      +

      Пример: обновление задачи в списке без мутации — tasks.map(t => t.id === id ? {...t, done: true} : t): создаётся новый массив, где нужный элемент заменён на новый объект с изменённым полем, а все остальные элементы остаются теми же ссылками. Так реактивные системы могут быстро понять, что именно изменилось, сравнивая ссылки, а не обходя все поля.

      +

      Частое заблуждение: новички считают, что порядок spread не важен — «ведь мы просто объединяем объекты». На деле {...defaults, ...userConfig} и {...userConfig, ...defaults} дадут разные результаты: во втором случае defaults перезапишет пользовательские настройки, что обычно не то, что нужно. Порядок «от общего к частному» стоит проверить в сегодняшней задаче на merge конфигураций.

      Ключевая мысль: spread для merge и иммутабельного update; rest для «всё кроме».

      Читать: - learn.javascript.ru: Деструктурирующее присваивание

      @@ -101,7 +109,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 06 day 2: destructuring spread"
      • @@ -114,14 +122,18 @@

        Ловушки

      День 3 (Wed): DOM — поиск и изменение элементов

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к DOM Todo App

      Теория

      DOM (Document Object Model) — программный интерфейс к HTML-дереву. Браузер парсит разметку и строит дерево узлов; JavaScript может читать и изменять это дерево — текст обновляется на экране мгновенно. Поиск элементов: document.querySelector('.card') — первый; querySelectorAll — NodeList всех совпадений; getElementById — по id.

      textContent устанавливает текст и экранирует HTML — безопасно для пользовательского ввода. innerHTML парсит HTML-строку — XSS-уязвимость, если вставляешь данные пользователя. Создавай элементы через createElement, append, remove — чистый DOM API.

      classList.add/remove/toggle/contains управляет классами без перезаписи всего className. dataset маппит data-*: el.dataset.pricedata-price. Кэшируй частые querySelector в объект elements — меньше обходов дерева.

      +

      Ментальная модель: до сих пор JS был отдельно от страницы — вычислял что-то в Console, не трогая экран. DOM API — это мост между кодом и тем, что видит пользователь: HTML создаёт начальное дерево, а дальше JS может строить, изменять и удалять узлы этого дерева точно так же, как строил бы данные в объекте или массиве. Разница в том, что каждое изменение дерева браузер сразу же перерисовывает на экране.

      +

      Почему это важно дальше: сегодняшний навык — основа для всей недели и всего DOM Todo App: добавление задачи в интерфейсе — это буквально createElement + append; удаление — remove(). Без уверенного владения поиском и изменением элементов невозможно перейти к событиям (завтра) и интерактивному UI (позже на неделе).

      +

      Пример: вывод пользовательского имени на страницу через card.innerHTML = userName кажется удобным, но если userName содержит <img src=x onerror="alert(1)">, браузер выполнит этот код как разметку — классическая XSS-атака. card.textContent = userName в той же ситуации просто покажет текст как есть, безопасно экранировав спецсимволы.

      +

      Частое заблуждение: новички считают innerHTML универсальным способом «вставить что угодно», не задумываясь об источнике данных. Правило простое: innerHTML допустим только для доверенной, статичной разметки (например, шаблона из твоего же кода), а любые данные, пришедшие от пользователя или внешнего API, должны идти через textContent или createElement — это и отрабатывается в сегодняшней практике на карточках товаров. Ещё одна ловушка — частые обращения к querySelector внутри циклов или обработчиков: каждый вызов заново обходит дерево DOM, поэтому ссылки на часто используемые элементы стоит один раз сохранить в объекте и переиспользовать.

      Ключевая мысль: DOM — живое дерево; textContent для текста, createElement вместо innerHTML с user input.

      Читать: - learn.javascript.ru: DOM-дерево @@ -151,21 +163,25 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 06 day 3: dom manipulation"

      День 4 (Thu): События — основы

      -

      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к DOM Todo App

      Теория

      События — способ браузера сообщить JS: «пользователь что-то сделал». addEventListener('click', handler) — современный стандарт; inline onclick в HTML — устарел и смешивает разметку с логикой. На один элемент можно повесить несколько обработчиков; onclick перезаписывает предыдущий.

      Объект события (event) несёт контекст: target — элемент, на котором сработало событие; currentTarget — элемент, на котором висит listener. preventDefault() отменяет действие браузера (submit формы, переход по ссылке), но не останавливает всплытие. stopPropagation() останавливает bubbling.

      Всплытие (bubbling): клик по кнопке внутри li внутри ul сначала срабатывает на кнопке, затем всплывает к li, ul, body, document. Делегирование: один listener на ul ловит клики по всем li — эффективно для динамических списков. Для снятия обработчика нужна именованная функция — анонимную removeEventListener не найдёт.

      +

      Ментальная модель: представь всплытие как круги на воде: бросаешь камень (клик) в конкретную точку (элемент), а волна расходится наружу через всех родителей до самого document. Делегирование пользуется этим эффектом: вместо того чтобы ставить сторожа (listener) у каждого маленького элемента, ты ставишь одного сторожа на общий контейнер — он «слышит» волну от любого клика внутри и по event.target понимает, где именно она началась.

      +

      Почему это важно дальше: делегирование — обязательный приём для динамических списков (Todo App этой недели, где задачи добавляются и удаляются во время работы страницы). Если вешать listener на каждый элемент списка отдельно, новые элементы, добавленные позже, окажутся без обработчика — типичный источник бага «кнопка удаления не работает у новых задач».

      +

      Пример: список задач с одним обработчиком на ul: list.addEventListener('click', e => { if (e.target.matches('.delete-btn')) removeTask(e.target.closest('li').dataset.id) }). Этот код продолжит работать для любой новой задачи, добавленной позже, потому что слушатель висит не на кнопках, а на их общем родителе.

      +

      Частое заблуждение: новички думают, что preventDefault() останавливает и всплытие события — но это не так, эти два механизма независимы. preventDefault() отменяет действие браузера по умолчанию (переход по ссылке, отправку формы), а stopPropagation() останавливает распространение события вверх по дереву. Спутав их, легко получить форму, которая не перезагружает страницу, но клик по ней всё равно «протекает» на родительские обработчики — это стоит явно проверить в сегодняшней задаче с stopPropagation.

      Ключевая мысль: bubbling — основа делегирования; preventDefaultstopPropagation.

      Читать: - learn.javascript.ru: Введение в события

      @@ -194,21 +210,25 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 06 day 4: events delegation"

      День 5 (Fri): Интерактивный UI

      -

      Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к DOM Todo App

      Теория

      Интерактивный UI строится на переключении состояний: открыт/закрыт, активен/неактивен. Скрытие: атрибут hidden, класс .is-open, aria-hidden="true" для скринридеров — лучше в комбинации. Таб-интерфейс: одна панель видима, остальные скрыты; активный таб помечается классом и aria-selected.

      Модальное окно — фокус внутри диалога (focus trap): Tab не уходит за пределы. Закрытие по Escape, клику на overlay, кнопке «×». body { overflow: hidden } при открытой модалке блокирует скролл фона. event.target.closest('.card') поднимается от точки клика к ближайшему предку с классом — паттерн делегирования для карточек.

      Аккордеон: aria-expanded на кнопке отражает состояние секции — обязательно для доступности. Всё это achievable без React — чистый DOM + классы + события.

      +

      Ментальная модель: любой интерактивный UI-компонент можно описать как автомат с конечным числом состояний: модалка «открыта» или «закрыта», таб «активен» или нет. Задача JS — не «рисовать» интерфейс заново каждый раз, а переключать состояние (обычно через класс или атрибут) и позволить CSS решить, как это состояние выглядит визуально. DOM в этой модели — просто зеркало текущего состояния, а не источник истины.

      +

      Почему это важно дальше: ровно этот подход — «состояние определяет вид» — лежит в основе React и других современных фреймворков, только там переключение состояния автоматически вызывает перерисовку. Отрабатывая аккордеон и табы на чистом JS сейчас, ты позже быстрее поймёшь, зачем вообще нужен фреймворк поверх этой идеи.

      +

      Пример: аккордеон без библиотек: клик по заголовку переключает класс .is-open у секции и aria-expanded у кнопки одновременно — section.classList.toggle('is-open'); button.setAttribute('aria-expanded', isOpen). CSS через .is-open { max-height: ... } показывает содержимое — JS не занимается анимацией напрямую, только состоянием.

      +

      Частое заблуждение: новички считают доступность (ARIA) «опциональной красотой для галочки». На деле aria-expanded/aria-hidden — это единственный способ, которым скринридер узнаёт о состоянии визуального компонента: без них пользователь с экранным диктором не поймёт, открыта секция или нет, даже если зрячему пользователю всё очевидно по анимации. Похожая ошибка — закрывать модалку только по клику на «×», забывая про Escape и клик по overlay: пользователь, привыкший к стандартному поведению модалок, будет считать интерфейс сломанным. Это стоит закрепить в сегодняшней практике на аккордеоне и модалке.

      Ключевая мысль: UI = состояние + DOM; ARIA синхронизирует визуал со скринридером.

      Читать: - learn.javascript.ru: Действия браузера

      @@ -244,14 +264,18 @@

      Git

      День 6 (Sat): Формы и валидация на JS

      -

      Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к DOM Todo App

      Теория

      HTML5-валидация — первый рубеж; JavaScript добавляет кастомную логику и UX. form.elements — коллекция полей формы; FormData собирает пары name–value; input.value, checkbox.checked — чтение состояния. Событие input срабатывает на каждый символ; change — при потере фокуса или выборе из select.

      Constraint Validation API: field.validity (флаги ошибок), field.validationMessage, setCustomValidity('текст') — переопределяет сообщение браузера. form.checkValidity() — программная проверка перед submit. Показывай ошибки в <span class="error"> под полем с aria-describedby — лучше одного alert().

      Disable кнопку submit, пока форма невалидна — предотвращает лишние попытки. HTML5 + JS вместе: нативные required/pattern + кастом «пароли совпадают» через setCustomValidity.

      +

      Ментальная модель: валидацию удобно представлять как два рубежа обороны. Первый — HTML5-атрибуты (required, pattern, type="email") — быстрый и бесплатный, браузер сам показывает стандартное сообщение. Второй — JS-логика для правил, которые HTML5 не умеет выразить (совпадение паролей, проверка на сервере, кастомные форматы) — здесь ты сам решаешь, когда показать ошибку и как её сформулировать.

      +

      Почему это важно дальше: формы — точка входа пользовательских данных в любое приложение, и на неделе 7 та же форма отправит данные через fetch на сервер. Уже сейчас важно приучиться не доверять вводу вслепую: проверка на клиенте улучшает UX (мгновенная обратная связь), но не заменяет проверку на сервере — клиентский JS всегда можно отключить или обойти.

      +

      Пример: живая проверка email при каждом вводе символа — emailInput.addEventListener('input', () => { errorSpan.textContent = emailInput.validity.valid ? '' : 'Введите корректный email' }). Пользователь видит ошибку сразу после того, как начал печатать неправильный адрес, а не только после попытки отправить форму.

      +

      Частое заблуждение: новички показывают ошибки валидации через alert(), что прерывает работу пользователя навязчивым модальным окном и не указывает конкретное проблемное поле. Правильный паттерн — вывод текста ошибки рядом с полем через <span class="error">, связанный с input через aria-describedby — так ошибка видна в контексте и доступна для скринридеров. Ещё одна частая недоработка — валидировать только при submit, из-за чего пользователь узнаёт об ошибке в пароле лишь после заполнения всей формы; событие input решает это, показывая проблему сразу. Это — основа сегодняшней практики.

      Ключевая мысль: input для live-валидации; ошибки у поля, не в alert; setCustomValidity для своих правил.

      Читать: - learn.javascript.ru: Формы, элементы управления

      @@ -280,21 +304,25 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 06 day 6: form validation"

      День 7 (Sun): DOM-проект — интерактивный лендинг

      -

      Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к DOM Todo App

      Теория

      Зрелое DOM-приложение разделяет слои. Data layer — массив задач, чистые функции addTask, toggleTask; не знает о HTML. DOM layer — renderTasks(tasks), renderFilters(); читает data, обновляет дерево. App layer — связывает события с изменением data и вызовом render. Базовый MVC без фреймворка.

      DocumentFragment — контейнер в памяти: наполни список элементами, один append fragment — один reflow вместо N. Производительность: кэшируй DOM-ссылки; не читай offsetHeight и не пиши style вперемешку (layout thrashing). requestAnimationFrame — обзор для плавных анимаций чисел и скролла.

      Функции render* — единая точка отрисовки: изменил data → вызвал renderTasks() → DOM синхронизирован. Todo App недели — CRUD через DOM, delegation на списке, фильтры, без innerHTML для user input.

      +

      Ментальная модель: разделение на data layer и DOM layer — это разделение «что происходит» и «как это выглядит». Данные (массив задач) — источник истины, независимый от экрана; DOM — просто их визуальное отражение в конкретный момент. Каждое изменение проходит по циклу: меняем данные → вызываем один и тот же render* → DOM обновляется целиком по актуальным данным, а не точечными правками в разных местах кода.

      +

      Почему это важно дальше: этот цикл «данные → render → DOM» — упрощённая версия того, как работает React и другие декларативные фреймворки: там ты тоже описываешь UI как функцию от состояния, а библиотека сама решает, что обновить на экране. Освоив паттерн вручную сейчас, ты поймёшь, зачем вообще нужен React, когда дойдёшь до него.

      +

      Пример: без разделения слоёв удаление задачи выглядело бы как ручной поиск нужного <li> в DOM и его удаление в нескольких разных обработчиках. С разделением: removeTask(id) меняет только массив данных, а единственный вызов renderTasks() перерисовывает список целиком — на 50 задач и на 5000 логика одна и та же, разница только в производительности, которую решает DocumentFragment.

      +

      Частое заблуждение: новички считают частые обращения к innerHTML для вставки списка «более простым» способом, чем render* с DOM API — код действительно короче, но при user input (например, названии задачи) это открывает XSS, а также требует полной пересборки строки при каждом малейшем изменении. Итоговый Todo App должен использовать createElement/append внутри renderTasks(), что и проверяют критерии сегодняшней практики.

      Ключевая мысль: data отдельно от DOM; render* — мост; fragment — batch insert без лишних reflow.

      Читать: - MDN: DocumentFragment

      @@ -323,7 +351,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 06 day 7: dom todo app final"
      • diff --git a/docs/w/07.html b/docs/w/07.html index 13d8545..6cfa14c 100644 --- a/docs/w/07.html +++ b/docs/w/07.html @@ -22,14 +22,18 @@

        День 1 (Mon): localStorage и sessionStorage

        -

        Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
        -Время (лайт): ~35м теория · ~1.5ч практика (MVP) · ~10м Git
        +

        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
        +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
        Связь с проектом: шаг к Notes Dashboard

        Теория

        Web Storage API даёт браузеру простое key-value хранилище, привязанное к origin (протокол + домен + порт). localStorage и sessionStorage работают одинаково по API, но различаются временем жизни: localStorage сохраняет данные между сессиями, а sessionStorage очищается при закрытии вкладки. Оба интерфейса принимают только строки — если нужно сохранить объект или массив, сначала сериализуй его через JSON.stringify, а при чтении восстанови через JSON.parse.

        Основные методы: setItem(key, value), getItem(key) (возвращает null, если ключа нет), removeItem(key) и clear(). API синхронный: каждая операция выполняется на main thread, поэтому не стоит записывать большие объёмы данных за раз. Типичный лимит — около 5 МБ на origin; при переполнении браузер выбросит QuotaExceededError.

        Для настроек UI (тема, язык, черновики форм) localStorage — естественный выбор. Но это не защищённое хранилище: любой JavaScript на странице (в том числе внедрённый через XSS) может прочитать все ключи. Пароли, JWT и API-ключи в localStorage хранить нельзя. Пользователь или расширение браузера могут вручную изменить значение в DevTools — поэтому JSON.parse всегда оборачивай в try/catch и задавай разумные значения по умолчанию при ошибке.

        +

        Ментальная модель: localStorage удобно представлять как блокнот, лежащий прямо в браузере пользователя, а не в твоём приложении. Блокнот привязан не к вкладке и не к сессии, а к конкретному origin — открыл тот же сайт неделю спустя, а записи всё ещё там. Но это чужой блокнот: любой скрипт на странице может его читать и писать, поэтому в нём нельзя хранить секреты, только то, что не страшно потерять или показать посторонним.

        +

        Почему это важно дальше: сегодняшний навык — первый шаг к тому, чтобы приложение «помнило» пользователя без сервера и базы данных. На неделе к проекту Notes Dashboard localStorage станет основным хранилищем заметок, а на будущих неделях с backend ты увидишь, что именно осознание уязвимости localStorage к XSS объясняет, почему токены авторизации в реальных production-приложениях чаще хранят в httpOnly cookie, а не здесь.

        +

        Пример: сохранение массива задач — localStorage.setItem('tasks', JSON.stringify(tasks)), восстановление — const saved = localStorage.getItem('tasks'); const tasks = saved ? JSON.parse(saved) : []. Проверка saved ? до парсинга защищает от попытки распарсить null, если ключ ещё не создавался — частая причина ошибки при первом запуске приложения.

        +

        Частое заблуждение: новички думают, что localStorage может хранить объекты и массивы напрямую, и пишут localStorage.setItem('user', user) без JSON.stringify. На деле любое значение молча приводится к строке — объект превратится в бесполезную строку "[object Object]", из которой ничего не восстановить. Сериализация через JSON — не опция, а обязательный шаг, который отрабатывается в сегодняшней практике на функциях saveState/loadState.

        Читать: - MDN: Window.localStorage - MDN: Web Storage API @@ -73,14 +77,18 @@

        Ловушки

      День 2 (Tue): JSON и работа с данными

      -

      Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~35м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Notes Dashboard

      Теория

      JSON (JavaScript Object Notation) — текстовый формат обмена данными между клиентом, сервером и файлами. Он поддерживает объекты, массивы, строки, числа, true/false и null, но не функции, undefined и комментарии. При JSON.stringify объекты Date превращаются в ISO-строки, а undefined в свойствах объекта просто опускаются — это важно помнить при экспорте данных.

      Метод JSON.stringify(obj, replacer, space) умеет фильтровать поля (через массив ключей или функцию-replacer) и форматировать вывод: space: 2 делает JSON читаемым для человека при отладке. Обратная операция — JSON.parse, которая бросает SyntaxError на невалидном тексте. Импорт из файла всегда требует валидации: проверь наличие обязательных полей, типы и допустимые значения до того, как смешаешь чужие данные со своим состоянием.

      В приложениях с localStorage данные со временем меняют форму. Добавь поле schemaVersion в сохраняемый объект — при загрузке сравни версию и при необходимости мигрируй старый формат в новый. Обновления списков объектов делай иммутабельно: items.map(item => item.id === id ? { ...item, title } : item) вместо прямой мутации элемента массива. Так проще отслеживать изменения и избегать побочных эффектов.

      +

      Ментальная модель: JSON удобно представлять как универсальный «переводчик» между живыми JS-объектами в памяти и текстом, который можно сохранить в файл, отправить по сети или положить в localStorage. stringify — перевод «объект → текст», parse — обратный перевод «текст → объект». Важно помнить, что перевод не идеален: некоторые вещи (функции, undefined, Date как объект) в JSON не выражаются напрямую и либо теряются, либо превращаются в упрощённую форму (строку).

      +

      Почему это важно дальше: JSON — универсальный язык обмена данными, на котором будет разговаривать твой код с любым сервером на неделе 8 и дальше: любой ответ от Fetch API, который ты получишь завтра, придёт именно в этом формате. А привычка валидировать импортированные данные до того, как смешать их со своим состоянием, защищает приложение от падения при получении неожиданного формата — что произойдёт неизбежно при работе с реальными внешними данными.

      +

      Пример: экспорт задач для скачивания — JSON.stringify(tasks, null, 2) создаёт читаемый, отформатированный текст с отступом в 2 пробела вместо сплошной строки — это то самое space, которое пригодится при отладке в консоли. При импорте того же файла JSON.parse(text) вернёт исходный массив объектов, и на этом этапе стоит сразу проверить, что каждый элемент содержит обязательные поля id, title.

      +

      Частое заблуждение: новички считают, что раз JSON.parse(JSON.stringify(obj)) возвращает «тот же» объект, значит JSON сохраняет абсолютно всё. На деле это популярный, но неполный способ глубокого клонирования: методы объекта, undefined-свойства и специальные типы вроде Map/Set при этом теряются молча, без предупреждения. Для задач сегодняшней практики (Todo-объекты с простыми полями) это не проблема, но важно понимать границу метода.

      Читать: - MDN: Working with JSON - MDN: JSON.stringify() @@ -111,21 +119,25 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 07 day 2: json import export"

      День 3 (Wed): Fetch API — основы

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Notes Dashboard

      Теория

      Fetch API — современный способ делать HTTP-запросы из браузера. Вызов fetch(url) сразу возвращает Promise, который разрешается объектом Response, ещё до того как тело ответа полностью загружено. Чтобы получить JSON, нужна вторая асинхронная операция: response.json(), которая тоже возвращает Promise. Типичная цепочка: fetch(url).then(r => r.json()).then(data => ...).

      Важная особенность: fetch не отклоняет Promise при HTTP-ошибках вроде 404 или 500. Promise reject происходит только при сетевых сбоях (нет интернета, CORS, таймаут DNS). Поэтому всегда проверяй response.ok (это shorthand для статусов 200–299) и обрабатывай неуспешные ответы явно — выброси ошибку или верни понятное сообщение пользователю.

      Для POST-запросов передай объект опций вторым аргументом: method: 'POST', headers: { 'Content-Type': 'application/json' } и body: JSON.stringify(data). Без правильного Content-Type сервер может не распознать тело как JSON. Для обучения удобен JSONPlaceholder — бесплатный mock REST API без регистрации, имитирующий посты, пользователей и комментарии.

      +

      Ментальная модель: fetch удобно представлять как письмо, отправленное по почте, а не телефонный звонок. Ты не получаешь ответ мгновенно — Promise возвращается сразу, но означает лишь «письмо отправлено», а не «ответ получен». .then() — это момент, когда почтальон приносит ответ; если ответов нужно два (сначала «получил ли сервер запрос вообще», потом «что внутри тела ответа»), их приходится ждать по очереди, отсюда и двухступенчатая цепочка fetch(url).then(r => r.json()).

      +

      Почему это важно дальше: Fetch — единственный способ получить данные с сервера из браузера, и с этого дня почти каждый проект курса будет обращаться к какому-нибудь API. На неделе 8 та же цепочка .then() перепишется на async/await — синтаксически проще, но модель поведения (Promise, отдельная обработка сетевых и HTTP-ошибок) останется точно такой же, так что сегодняшнее понимание не станет устаревшим.

      +

      Пример: fetch('https://jsonplaceholder.typicode.com/posts/9999') вернёт успешно разрешённый Promise с response.status === 404, а не ошибку — сеть отработала штатно, просто сервер сообщил «не найдено». Только fetch('https://несуществующий-домен.test') (сеть недоступна) действительно приведёт к .catch().

      +

      Частое заблуждение: самая частая ошибка новичков — писать fetch(url).then(data => console.log(data.title)), ожидая сразу получить готовый объект. На деле первый .then() получает объект Response (метаданные: статус, заголовки), а не тело ответа — тело нужно отдельно распарсить через response.json(), который тоже асинхронный и требует своего .then(). Именно эта двухступенчатая цепочка отрабатывается в сегодняшней функции fetchJson.

      Читать: - learn.javascript.ru: Fetch - MDN: Using Fetch @@ -156,21 +168,25 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 07 day 3: fetch api basics"

      День 4 (Thu): Работа с публичными API

      -

      Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~35м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Notes Dashboard

      Теория

      Публичные REST API организуют данные вокруг ресурсов — сущностей вроде «пользователь», «пост» или «город». URL описывает что запрашиваешь (/users/42), а HTTP-метод — какое действие выполняешь (GET — прочитать, POST — создать). Ответ сервера сопровождается статус-кодом: 200 — успех, 201 — создано, 400 — ошибка клиента, 404 — не найдено, 500 — ошибка сервера. Умение читать статус и тело ответа — базовый навык интеграции.

      Параметры запроса передаются в query string: ?q=moscow&page=2. Спецсимволы и пробелы кодируй через URLSearchParams, а не вручную — иначе поиск по «New York» сломается. Перед интеграцией изучи документацию API: какие endpoints доступны, какие поля обязательны, есть ли лимиты на количество запросов (rate limiting). OpenAPI/Swagger-спецификация — стандартный формат, где всё это описано машиночитаемо.

      CORS (Cross-Origin Resource Sharing) — механизм безопасности браузера. Если твой сайт на localhost:5500, а API на другом домене, браузер спросит сервер: «разрешён ли этот origin?». Если сервер не вернёт нужные заголовки (Access-Control-Allow-Origin), fetch заблокируется — это не баг твоего кода, а политика браузера. API-ключи в production-коде на клиенте видны всем — для секретных ключей нужен backend-прокси.

      +

      Ментальная модель: REST API удобно представлять как каталог товаров в магазине с чёткой системой адресов: URL — это адрес полки (/users/42 — полка «пользователь номер 42»), а HTTP-метод — действие с этой полкой (GET — посмотреть, POST — положить новое, DELETE — убрать). Такая единообразная адресация позволяет, не читая документацию каждого конкретного API с нуля, догадаться о структуре по аналогии с уже знакомыми.

      +

      Почему это важно дальше: реальные проекты почти всегда строятся вокруг стороннего или собственного API — умение быстро прочитать документацию, понять доступные endpoints и правильно интерпретировать статус-коды экономит часы отладки. CORS — это то, с чем ты гарантированно столкнёшься, как только начнёшь подключать любой внешний сервис, и важно сразу понимать: ошибка CORS в консоли означает «сервер не разрешил», а не «код неправильный».

      +

      Пример: запрос погоды для города с пробелом в названии — fetch('https://api.example.com/weather?city=' + encodeURIComponent('Нижний Новгород')) или через URLSearchParams: const params = new URLSearchParams({ city: 'Нижний Новгород' }); fetch('https://api.example.com/weather?' + params). Без кодирования пробел и кириллица в URL могут сломать запрос или интерпретироваться сервером неправильно.

      +

      Частое заблуждение: новички, столкнувшись с ошибкой CORS в консоли, пытаются «исправить» её в своём JS-коде — но CORS настраивается на сервере, а не на клиенте, и обойти его на фронтенде штатными средствами невозможно (и не нужно, это защита пользователя). Если сервер действительно не поддерживает CORS для твоего случая, единственный легитимный вариант — свой backend-прокси, который сегодняшняя практика пока не требует, но важно понимать причину ограничения.

      Читать: - MDN: CORS - MDN: HTTP Overview @@ -201,21 +217,25 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      +

      Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 07 day 4: public apis weather github"

      День 5 (Fri): ES-модули

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Notes Dashboard

      Теория

      ES-модули — стандартный способ организации JavaScript-кода в файлах с явными зависимостями. Каждый файл — отдельный модуль со своей областью видимости: переменные не попадают в глобальный window. Чтобы сделать функцию или константу доступной снаружи, используй export. Импорт: import { fetchPosts } from './api.js' для именованного экспорта или import render from './render.js' для default.

      В HTML подключай модули через <script type="module" src="main.js">. Такой скрипт выполняется в strict mode, откладывается (defer) и загружается как модуль — браузер сам разрешит дерево зависимостей. В пути импорта обязательно указывай расширение .js — в отличие от bundler-ов, нативные модули в браузере этого требуют. Открытие файла через file:// не сработает из-за CORS; нужен локальный HTTP-сервер (Live Server, npx serve).

      Именованный export предпочтителен, когда из файла экспортируется несколько сущностей — имена явные при импорте и рефакторинге. Default export удобен для «главной» сущности файла (один компонент, один класс). Типичная структура проекта: api/ — запросы, ui/ — рендер DOM, utils/ — хелперы, main.js — точка входа, которая только связывает модули.

      +

      Ментальная модель: до модулей весь JS-код жил в одной большой общей комнате (глобальная область видимости window) — любая переменная была видна отовсюду, и случайное совпадение имён в разных файлах могло незаметно всё сломать. Модули — это отдельные комнаты с закрытыми дверями: то, что не экспортировано явно через export, остаётся приватным для файла, а import — единственный «дверной проём», через который одна комната может попросить что-то у другой.

      +

      Почему это важно дальше: структура api/ui/utils/main.js — это упрощённая версия архитектуры, которую ты увидишь в любом современном фронтенд-проекте, включая React-приложения дальше по курсу: разделение на слои по ответственности, а не по случайному принципу «файл разросся — создам новый». Умение аккуратно резать монолитный app.js на модули — прямая тренировка рефакторинга больших кодовых баз.

      +

      Пример: storage.js экспортирует export function saveTasks(tasks) {...} и export function loadTasks() {...}, а main.js импортирует import { saveTasks, loadTasks } from './storage.js'. Такой файл storage.js можно переиспользовать в другом проекте без единой правки — он не знает ничего о DOM или конкретных задачах, только про чтение/запись данных.

      +

      Частое заблуждение: новички забывают указать .js в пути импорта (import { x } from './utils' вместо './utils.js') по привычке из bundler-based проектов (Webpack, Vite), где расширение можно опустить. Нативные ES-модули в браузере таких «магических» разрешений путей не делают — без явного расширения браузер выдаст ошибку загрузки модуля, что стоит сразу проверить при первом запуске через Live Server.

      Читать: - learn.javascript.ru: Модули - MDN: JavaScript modules @@ -253,14 +273,18 @@

      Git

      День 6 (Sat): Формы и API вместе

      -

      Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~35м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Notes Dashboard

      Теория

      Связка HTML-форм и fetch — типичный сценарий создания данных на сервере. Перехвати событие submit, вызови e.preventDefault(), собери данные из полей и отправь POST-запрос с body: JSON.stringify(formData) и заголовком Content-Type: application/json. Для форм с файлами удобнее FormData — он автоматически формирует multipart-тело. На время запроса отключай кнопку submit, чтобы пользователь не отправил дубликат.

      Поиск по API при каждом нажатии клавиши создаёт лишнюю нагрузку. Debounce откладывает вызов функции до паузы в вводе (обычно 300 мс): пока пользователь печатает, запросы не уходят. Если запрос уже в полёте, а пользователь изменил запрос, старый ответ может прийти позже нового и перезаписать актуальные данные — race condition. AbortController решает это: передай signal в fetch и вызови abort() при новом вводе или в cleanup.

      Optimistic UI обновляет интерфейс до ответа сервера («пост уже в списке»), создавая ощущение мгновенности. Но при ошибке сервера нужен rollback — убрать добавленный элемент и показать сообщение. Баланс между скоростью отклика и надёжностью — ключевой навык при работе с формами и API.

      +

      Ментальная модель: debounce удобно представлять как секретаря, который не бежит выполнять поручение при каждом слове, а ждёт паузы в речи и выполняет только последнюю, окончательную просьбу. Применительно к поиску: пока пользователь печатает «Москва» по буквам, отправлять запрос на каждую букву («М», «Мо», «Мос»...) бессмысленно — нужен только финальный запрос, когда ввод остановился хотя бы на 300 мс.

      +

      Почему это важно дальше: debounce и AbortController — это база для любого «живого» поиска в реальных приложениях, от простого автокомплита до сложных дашбордов. Race condition (когда устаревший ответ приходит позже нового и портит UI) — один из самых незаметных багов в асинхронном коде: тесты часто его не ловят, а пользователи с медленным интернетом сталкиваются регулярно. Умение защититься от него сейчас избавит от часов отладки в будущих проектах.

      +

      Пример: без debounce поиск пользователей GitHub при вводе «cursor» отправит 6 запросов подряд (по одному на каждую букву), и если ответ на «c» придёт позже ответа на «cursor» (сеть непредсказуема), список покажет результаты для одной буквы поверх правильных. С debounce(search, 300) уйдёт только один запрос — после того как пользователь на 300 мс перестал печатать.

      +

      Частое заблуждение: новички считают, что достаточно просто отключить кнопку submit на время запроса, чтобы избежать всех проблем с повторными действиями. Но при быстром вводе в поле поиска (без кнопки) проблема остаётся — race condition возникает именно между несколькими автоматическими запросами, а не только между кликами по кнопке; решает её именно AbortController.abort() для устаревших запросов, что и отрабатывается в сегодняшней практике.

      Читать: - MDN: Using Fetch — отправка данных - MDN: AbortController @@ -291,21 +315,25 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 07 day 6: forms api debounce"

      День 7 (Sun): Интеграционный проект

      -

      Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~35м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Notes Dashboard

      Теория

      Интеграционный проект недели объединяет всё изученное: модули, localStorage, fetch, формы. Архитектурно раздели код на слои: api — HTTP-запросы и парсинг ответов, cache — чтение/запись в storage с TTL, ui — рендер DOM и обработка событий, app — связывание слоёв. Модуль api не должен знать о DOM, а ui не должен формировать URL запросов — так проще тестировать и менять каждую часть отдельно.

      Кэш с TTL (time-to-live) сохраняет объект { data, cachedAt } в localStorage. При загрузке сравни Date.now() - cachedAt с лимитом (например, 5 минут): если кэш свежий — покажи данные мгновенно, если нет — запроси с сервера и обнови кэш. При offline (можно симулировать в DevTools) покажи устаревший кэш с предупреждением вместо пустого экрана — это базовый offline-first подход.

      Оборачивай асинхронные операции в try/catch на границе слоёв: пользователь должен видеть понятное сообщение об ошибке, а не пустую страницу. Простой retry — повторить запрос 2–3 раза с задержкой при сетевом сбое. На следующей неделе этот код перепишется на async/await и Promise-утилиты, но принципы слоёв и обработки ошибок останутся.

      +

      Ментальная модель: зрелое приложение недели удобно представлять как небольшую компанию с чётким разделением обязанностей: api — «отдел закупок», который умеет только ходить наружу за данными и ничего не знает про интерфейс; cache — «склад», хранящий недавно полученное для быстрой выдачи; ui — «витрина», отвечающая только за то, что видит покупатель; app — «менеджер», который командует остальными отделами, но сам ничего не делает руками. Каждый отдел можно заменить или протестировать отдельно, не трогая остальные.

      +

      Почему это важно дальше: эта слоистая архитектура — не искусственное упражнение, а прямая репетиция того, как строятся production-приложения: разделение на data/network/presentation слои встречается и в vanilla JS, и в React, и в мобильной разработке. Кэш с TTL и offline-first подход — реальные требования, которые проверяющие (и будущие работодатели) ожидают видеть в серьёзном портфолио-проекте.

      +

      Пример: при повторном открытии дашборда функция getPosts() сначала проверяет кэш — const cached = JSON.parse(localStorage.getItem('posts_cache')); if (cached && Date.now() - cached.cachedAt < 5 * 60 * 1000) return cached.data; — и только если кэш устарел или отсутствует, идёт в сеть за свежими данными и обновляет cachedAt.

      +

      Частое заблуждение: новички смешивают весь код в одном app.js, где fetch, обработка ответа и обновление DOM идут подряд в одной функции — работает, пока проект маленький, но при добавлении кэша или изменении источника данных приходится переписывать всё сразу. Чёткое разделение на слои — не бюрократия, а страховка: изменение источника данных (например, переход с JSONPlaceholder на реальный backend) в правильно организованном проекте затронет только api.js, что и является целью финального рефакторинга в сегодняшней практике.

      Читать: - web.dev: Storage for the web - MDN: Fetch API @@ -336,7 +364,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 07 day 7: notes dashboard final"
      • diff --git a/docs/w/08.html b/docs/w/08.html index 69f14b0..08d6316 100644 --- a/docs/w/08.html +++ b/docs/w/08.html @@ -22,14 +22,17 @@

        День 1 (Mon): Асинхронность и Event Loop

        -

        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
        -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
        +

        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
        +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
        Связь с проектом: шаг к Movie Catalog

        Теория

        JavaScript однопоточен: в каждый момент времени выполняется только один фрагмент кода на main thread. Синхронные операции (циклы, тяжёлые вычисления) блокируют интерфейс — кнопки не реагируют, анимации замирают. Асинхронность решает это: долгие задачи (таймеры, сетевые запросы, чтение файлов) делегируются Web APIs браузера, а результат возвращается через колбэки, когда main thread освободится.

        Event Loop — механизм, который координирует выполнение. Call stack выполняет текущий синхронный код. Когда стек пуст, Loop проверяет очереди задач. Сначала выполняются microtasks (колбэки Promise: .then, .catch, queueMicrotask), и только потом macrotasks (setTimeout, setInterval, I/O). Поэтому Promise.resolve().then(...) всегда выполнится раньше setTimeout(fn, 0) — даже с нулевой задержкой.

        Классическая ловушка — думать, что setTimeout(fn, 0) выполнится «сразу». На самом деле он попадёт в macrotask queue и дождётся завершения всего синхронного кода и всех microtasks. Понимание этого порядка — основа отладки «почему console.log выводится не в том порядке, который я ожидал». Визуализатор Loupe помогает увидеть движение задач по очередям.

        +

        Хорошая мысленная модель — ресторанная кухня с одним поваром (main thread) и официантами (Web APIs). Повар не может делать два блюда одновременно, но может передать заказ на гриль (таймер, сетевой запрос) официанту и продолжить резать овощи. Когда гриль готов, официант кладёт тарелку в очередь готовых блюд — повар заберёт её, как только освободится. Так же Event Loop не выполняет асинхронные операции сам — он лишь решает, когда вернуть управление колбэку.

        +

        Понимание Event Loop критично не только для отладки порядка console.log. Это фундамент, на котором строятся Promise (дни 2–3 этой недели), рендеринг React (батчинг обновлений state — неделя 11) и производительность Node.js на бэкенде, где один процесс обслуживает тысячи соединений именно благодаря неблокирующей модели. Частое заблуждение новичков — думать, что Web Workers или async/await делают JavaScript многопоточным: на самом деле выполняется всё тот же один поток, просто задачи чередуются, а настоящий параллелизм (несколько ядер CPU) требует отдельных Worker-потоков с собственной памятью.

        +

        Конкретный пример: console.log('A'); setTimeout(() => console.log('B'), 0); Promise.resolve().then(() => console.log('C')); console.log('D') выведет A, D, C, B — синхронный код первым, затем microtask C, затем macrotask B, даже с нулевой задержкой таймера. Именно такие цепочки предстоит разобрать в первом задании практики: предсказание порядка вывода тренирует эту модель до автоматизма, а диаграмма в блокноте (шаг 3) закрепляет её визуально.

        Читать: - learn.javascript.ru: Введение: колбэки - javascript.info: Event loop @@ -74,14 +77,18 @@

        Ловушки

      День 2 (Tue): Promises — основы

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Movie Catalog

      Теория

      Promise — объект-обёртка над результатом асинхронной операции, который ещё неизвестен. У Promise три состояния: pending (ожидание), fulfilled (успех) и rejected (ошибка). Переход из pending возможен только один раз — после resolve или reject состояние не меняется. Это делает Promise предсказуемым контрактом: либо данные, либо ошибка.

      Создание: new Promise((resolve, reject) => { ... }). Потребление: .then(onFulfilled) для успеха, .catch(onRejected) для ошибок, .finally(onFinally) для cleanup в любом случае (скрыть loader, сбросить флаг загрузки). Каждый .then возвращает новый Promise — поэтому цепочки .then().then().catch() читаются сверху вниз без «callback hell» вложенных функций.

      Если .then-колбэк возвращает значение, следующий .then получит его. Если возвращает Promise, следующий .then дождётся его разрешения. Один .catch в конце цепочки перехватит reject из любого предыдущего звена. Promise.all([p1, p2]) запускает несколько Promise параллельно и ждёт все — но один reject роняет весь результат.

      +

      Удобная мысленная модель — талон в химчистке: ты оставляешь вещи (запускаешь асинхронную операцию) и получаешь квиток (Promise) прямо сейчас, а не сами вещи. Квиток можно передать другому человеку и объяснить, что делать с готовым результатом (.then) или с проблемой (.catch) — сама операция при этом продолжает выполняться независимо от того, смотришь ты на квиток или нет.

      +

      Это понимание — фундамент для async/await, который изучается уже завтра: await — это просто способ «подождать квиток», не потеряв читаемость кода. Позже, при работе с React Query или SWR, ты снова встретишь Promise как базовую единицу асинхронного состояния. Частое заблуждение — считать, что код внутри new Promise((resolve) => {...}) выполняется асинхронно: на самом деле executor запускается синхронно и немедленно, а асинхронной становится только реакция через .then.

      +

      Пример: new Promise((resolve) => { console.log('1'); resolve('done'); }).then(v => console.log(v)); console.log('2') выведет 1, 2, done — executor отработал сразу, а .then дождался, пока текущий синхронный код (лог '2') закончится. В практике дня ты обернёшь setTimeout в delay(ms) (шаг 1) — стандартный паттерн превращения callback-based API в Promise-based, который пригодится для любой асинхронной функции без нативной поддержки Promise.

      +

      Ещё один нюанс, который легко упустить: Promise может завершиться только один раз — повторный вызов resolve после первого resolve или reject просто игнорируется движком. Это гарантирует, что .then никогда не сработает дважды с разными значениями, и делает Promise надёжнее «сырых» колбэков, которые можно вызвать сколько угодно раз по ошибке.

      Читать: - learn.javascript.ru: Промисы - learn.javascript.ru: Цепочка промисов @@ -112,15 +119,15 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      +

      Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 08 day 2: promises chaining"

      День 3 (Wed): async/await

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Movie Catalog

      Теория

      @@ -133,6 +140,10 @@

      Теория

      }

      Главная ловушка — последовательный await в цикле: for (const id of ids) { await fetch(id) } выполнит N запросов по очереди. Если запросы независимы, собери массив Promise и дождись всех: await Promise.all(ids.map(id => fetch(id))). В ES-модулях доступен top-level await — можно писать const config = await fetch('/config.json') прямо в main.js без обёртки.

      +

      Мысленно async/await — это «закладка» в книге: await не останавливает всю программу, а лишь запоминает место в текущей функции и отдаёт управление дальше, чтобы вернуться сюда, когда результат будет готов. Другие функции, таймеры и обработчики событий продолжают работать как ни в чём не бывало — блокируется только логика внутри конкретной async-функции.

      +

      Этот паттерн станет основным способом работы с данными на неделях 10–11: типизированные API-функции (Promise<T> в TypeScript) и хуки React (useEffect с async-логикой внутри) опираются именно на async/await, а не на явные цепочки .then. Частое заблуждение — думать, что await можно использовать где угодно: без async на функции или на верхнем уровне обычного скрипта (не ES-модуля) движок выбросит SyntaxError.

      +

      Пример цены последовательного await: 10 запросов по 200мс каждый в цикле for...of с await дадут итог около 2 секунд, потому что каждый следующий запрос стартует только после ответа предыдущего. Заменив на await Promise.all(ids.map(id => fetch(id))), все запросы уйдут параллельно, и итог сократится примерно до 200мс. Именно это сравнение — шаг 6 практики дня (console.time) — наглядно покажет цену необдуманной последовательности и станет личным аргументом в пользу параллельных await, когда данные независимы.

      +

      Важно помнить и обратный случай: если второй запрос логически зависит от результата первого (например, сначала получить userId, потом по нему загрузить посты), последовательный await — не ошибка, а единственно верный вариант. Параллелить стоит только независимые операции — умение отличить одно от другого и есть суть архитектурного мышления, а не просто «await — плохо, Promise.all — хорошо».

      Читать: - learn.javascript.ru: Async/await - MDN: async function @@ -163,21 +174,24 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 08 day 3: async await refactor"

      День 4 (Thu): HTTP углублённо

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Movie Catalog

      Теория

      HTTP — протокол обмена сообщениями между клиентом и сервером. Каждый запрос состоит из метода, URL, заголовков и опционального тела. Ответ содержит статус-код, заголовки и тело. Методы несут семантику: GET читает ресурс (идемпотентен, кэшируем), POST создаёт новый, PUT/PATCH обновляют, DELETE удаляет. Понимание семантики помогает проектировать API и правильно обрабатывать ответы.

      Статус-коды сгруппированы: 1xx — информация, 2xx — успех (200 OK, 201 Created, 204 No Content), 3xx — перенаправление, 4xx — ошибка клиента (400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found), 5xx — ошибка сервера. Для UI важно различать 401 («войдите в систему») и 403 («у вас нет прав») — пользователю нужны разные сообщения.

      Заголовки передают метаданные: Content-Type описывает формат тела, Authorization — токен доступа, Cache-Control и ETag управляют кэшированием. CORS настраивается на сервере через заголовки вроде Access-Control-Allow-Origin. «Непростые» запросы (нестандартные заголовки, методы кроме GET/POST) вызывают preflight — браузер сначала отправит OPTIONS и спросит разрешение.

      +

      Мысленная модель HTTP — обмен письмами по строгим правилам почты: клиент пишет письмо (запрос) с адресом (URL), типом отправления (метод) и содержимым (тело), сервер отвечает своим письмом со штампом (статус-код) и вложениями (тело ответа). Оба участника не хранят состояние друг о друге между письмами — HTTP по своей природе stateless, поэтому авторизация передаётся заново в каждом запросе (заголовок Authorization), а не «запоминается» сервером автоматически.

      +

      Это понимание пригодится сразу при проектировании api-wrapper (шаг 2 практики) и в дальнейшем — при работе с REST API на бэкенде и при чтении документации любого стороннего сервиса, которая всегда описана в терминах методов, статусов и заголовков. Частое заблуждение новичков — путать 401 и 403: 401 означает «сервер не знает, кто ты» (нет или истёк токен, нужен логин), а 403 — «сервер знает, кто ты, но тебе запрещено» (например, обычный пользователь пытается зайти в админку). UI должен обрабатывать эти случаи по-разному: 401 → редирект на страницу входа, 403 → сообщение «недостаточно прав».

      +

      Конкретный пример CORS: фронтенд на localhost:3000 обращается к API на api.example.com — браузер блокирует ответ, если сервер не прислал заголовок Access-Control-Allow-Origin: http://localhost:3000 (или *). Это не ошибка сети и не баг клиента, а защитный механизм браузера, который стоит увидеть своими глазами в шаге 1 практики через вкладку Network: найди среди заголовков реального запроса те, что относятся именно к CORS и кэшированию.

      Читать: - MDN: HTTP Overview - MDN: CORS @@ -208,21 +222,24 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      +

      Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 08 day 4: http api wrapper"

      День 5 (Fri): Паттерны работы с API

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Movie Catalog

      Теория

      Работа с API в production выходит за рамки простого fetch(url). Пагинация делит большие наборы данных на страницы: offset/limit (?page=2&limit=20) прост в реализации, но нестабилен при вставках новых записей; cursor-based пагинация (?after=lastId) надёжнее для лент и поиска. Retry с exponential backoff повторяет упавший запрос с растущей задержкой (1с, 2с, 4с), не перегружая сервер при временных сбоях.

      Race condition возникает, когда быстрый новый запрос завершается раньше старого, но старый ответ приходит последним и перезаписывает актуальные данные. Решения: AbortController (отменить предыдущий fetch) или счётчик/request id (игнорировать устаревший ответ). Request deduplication не запускает второй идентичный запрос, пока первый ещё в полёте — полезно для кэширования в памяти.

      Паттерн stale-while-revalidate: сначала покажи кэшированные данные (мгновенный отклик), затем обнови фоном. Skeleton UI резервирует место под контент во время загрузки, снижая layout shift (CLS). Эти приёмы превращают «голый fetch» в устойчивый клиентский слой данных.

      +

      Мысленная модель здесь — работа диспетчера такси, а не одного водителя: диспетчер умеет распределять заказы (запросы), повторно назначать заказ при отказе водителя (retry), отменять устаревший заказ, если клиент уже уехал на другой машине (устаревший ответ при race condition), и показывать клиенту примерное время ожидания, пока машина едет (skeleton UI). Голый fetch(url) — это водитель без диспетчера: работает, пока всё идёт по плану, и ломается при малейшей нестабильности сети.

      +

      Эти паттерны становятся особенно важны в реальных продакшен-приложениях и позже — в библиотеках вроде React Query или SWR, которые фактически реализуют stale-while-revalidate, retry и дедупликацию «из коробки»; понимание паттернов вручную объясняет, что происходит «под капотом» таких библиотек, а не заставляет воспринимать их как магию. Частое заблуждение — считать race condition редкой экзотикой: на практике она возникает в любом live-поиске с debounce, где пользователь быстро меняет запрос, и старый ответ может прийти позже нового.

      +

      Конкретный пример: пользователь печатает «cat», затем быстро «dog» — уходят два запроса, но ответ на «cat» из-за сетевой задержки приходит позже ответа на «dog» и затирает актуальный результат неактуальным. Решение — AbortController.abort() на предыдущий запрос при старте нового, либо сравнение id запроса перед применением результата. Это именно тот сценарий, который нужно воспроизвести и исправить в шаге 5 практики дня — «отмена устаревшего ответа при быстром поиске».

      Читать: - JSON:API — Pagination - web.dev: Optimize LCP — skeleton и perceived performance @@ -260,14 +277,18 @@

      Git

      День 6 (Sat): Promise utilities

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Movie Catalog

      Теория

      Помимо базового Promise.all, в JavaScript есть набор утилит для разных сценариев. Promise.allSettled ждёт завершения всех Promise и возвращает массив { status, value/reason } — идеально, когда нужны результаты нескольких независимых API, даже если часть упала. Promise.race отдаёт результат первого завершившегося Promise — удобно для timeout-обёртки. Promise.any возвращает первый успешный, игнорируя reject (если все упали — AggregateError).

      Promise.all работает по принципу fail-fast: один reject ломает весь результат. Используй его, когда все данные обязательны (загрузка профиля + настроек одновременно). Promise.allSettled — когда частичный успех допустим (дашборд с виджетами от разных сервисов). Timeout через race: Promise.race([fetch(url), delay(5000).then(() => Promise.reject('timeout'))]).

      Необработанный reject (unhandledrejection) — сигнал, что где-то забыли .catch или try/catch. В production повесь глобальный listener window.addEventListener('unhandledrejection', ...) для логирования. for await...of позволяет последовательно обрабатывать асинхронные итерируемые источники без гонки параллельных запросов.

      +

      Мысленная модель — выбор инструмента под задачу, как в наборе отвёрток: Promise.all — это шуруп, который либо закручен полностью, либо задача провалена целиком (все данные обязательны); Promise.allSettled — гаечный набор, где допустимо закрутить не все гайки (дашборд из независимых виджетов); Promise.race — секундомер, который останавливается по первому событию, будь то успешный ответ или превышение таймаута.

      +

      Это понимание пригодится при построении дашбордов и агрегирующих экранов на протяжении всего курса: почти любой сложный UI загружает данные из нескольких источников с разной надёжностью, и выбор правильной Promise-утилиты определяет, упадёт ли весь экран из-за одного медленного виджета. Частое заблуждение — использовать Promise.all по умолчанию для всего подряд: если один из пяти виджетов дашборда временно недоступен, весь дашборд из-за Promise.all останется пустым экраном, хотя четыре виджета вполне могли отрендериться.

      +

      Конкретный пример timeout: Promise.race([fetch(url), new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 5000))]) — если fetch не успел за 5 секунд, race вернёт reject от таймера, а не будет ждать вечно зависший запрос. Такой withTimeout — это шаг 2 практики дня, и он же станет частью финального api-wrapper: без таймаута зависший запрос к нестабильному API способен «подвесить» весь пользовательский интерфейс на неопределённое время.

      +

      Отдельно стоит запомнить Promise.any: в отличие от race, который отдаёт первый результат вообще (успех или ошибка), any дожидается первого успешного ответа и игнорирует reject, пока не упадут все кандидаты — удобно для запроса к нескольким зеркалам одного API, где важен любой рабочий ответ, а не именно самый быстрый.

      Читать: - MDN: Promise.allSettled() - MDN: Promise.race() @@ -298,21 +319,24 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      +

      Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 08 day 6: promise utilities timeout"

      День 7 (Sun): Асинхронная архитектура

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Movie Catalog

      Теория

      Асинхронная архитектура приложения определяет, как слои общаются между собой. API-слой возвращает данные или бросает типизированную ошибку (ApiError со статусом) — он не знает о DOM и не решает, показать спиннер или toast. UI-слой подписывается на состояние и рендерит соответствующий экран. Между ними — слой состояния с явными фазами: idle | loading | success | error | empty.

      Явная state machine убирает «зависшие» экраны: в каждый момент UI находится ровно в одном состоянии, и переходы предсказуемы (loading → success или loading → error). Простой pub/sub (createAsyncState с subscribe/setState) даёт реактивность без фреймворка — задел на React hooks. При тестировании async-кода fetch можно подменить mock-функцией, возвращающей фиксированный Promise.

      На следующих неделях TypeScript добавит Promise<T> как контракт: async-функция документирует, какой тип данных вернётся. Сейчас зафиксируй принцип: асинхронность — это не только синтаксис, а разделение ответственности между запросом, состоянием и отображением.

      +

      Мысленная модель — конвейер на заводе с чёткими станциями: сырьё (запрос) поступает на станцию API, где либо превращается в готовую деталь (данные), либо помечается браком (ApiError) с понятной причиной. Дальше деталь попадает на станцию состояния, которая просто фиксирует текущую фазу конвейера, и только затем — на станцию сборки (UI), которая ничего не решает сама, а лишь отображает то, что сообщила предыдущая станция. Перепутай станции местами (например, дай UI напрямую вызывать fetch и решать, что показывать) — и конвейер быстро превратится в клубок проводов, который невозможно чинить.

      +

      Это разделение — прямая подготовка к React: useState/useReducer (неделя 11) — это, по сути, официальная реализация той же идеи «явное состояние + подписка на изменения», которую ты сегодня собираешь вручную через createAsyncState. Частое заблуждение начинающих — хранить состояние загрузки как отдельные булевы флаги (isLoading, isError, isEmpty), которые могут противоречить друг другу (например, isLoading = true и isError = true одновременно), вместо одного явного состояния, где такие противоречия структурно невозможны.

      +

      Пример на практике: функция search(query) в проекте «Каталог фильмов» должна явно переводить состояние idle → loading → success (нашлись фильмы), loading → empty (пустой результат) или loading → error (сеть упала) — и ни один компонент UI не должен сам решать, какой текст показать в каждом случае, кроме как читая это единственное состояние. Это и есть критерий «api / state / ui разделены» из чеклиста дня.

      Читать: - javascript.info: Промисы - patterns.dev: Observer Pattern @@ -343,7 +367,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

      Git

      • Закоммить изменения дня: git add ...git commit -m "week 08 day 7: movie catalog final"
      • diff --git a/docs/w/09.html b/docs/w/09.html index a6fa3d4..f23be5f 100644 --- a/docs/w/09.html +++ b/docs/w/09.html @@ -22,14 +22,17 @@

        День 1 (Mon): Scope и замыкания

        -

        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
        -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
        +

        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
        +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
        Связь с проектом: шаг к Library System

        Теория

        Область видимости (scope) определяет, где переменная доступна для чтения и записи. В JavaScript действует лексическая (статическая) область: функция «видит» переменные того места, где была объявлена, а не где вызвана. let и const создают блочную область ({ ... }), а устаревший var — функциональную, что приводит к неожиданным утечкам переменных из циклов.

        Замыкание (closure) возникает, когда внутренняя функция сохраняет доступ к переменным внешней функции даже после того, как внешняя завершила выполнение. Практически это означает: createCounter() возвращает функции increment и getValue, которые «помнят» переменную count в своём лексическом окружении. Замыкания — основа приватности данных без классов: createBankAccount(balance) скрывает баланс от внешнего кода.

        Классическая ловушка — цикл с var и setTimeout: все колбэки ссылаются на одну и ту же переменную i с финальным значением. let в цикле создаёт новую привязку на каждой итерации, решая проблему. Замыкания удерживают ссылки на внешние переменные и могут мешать сборщику мусора — не замыкай на большие объекты без необходимости.

        +

        Хорошая мысленная модель замыкания — рюкзак, который функция берёт с собой при рождении и никогда не снимает: внутри рюкзака лежат все переменные из окружения, где функция была объявлена. Даже если внешняя функция давно завершилась и, казалось бы, её данные должны исчезнуть, рюкзак продолжает их держать, пока жива хотя бы одна функция, которая на них ссылается — поэтому getValue() из createCounter() спустя сколько угодно вызовов «помнит» актуальное значение count.

        +

        Замыкания — это не просто приём для счётчиков: это основа модульного паттерна (день 5 этой недели), React-хуков (useState работает благодаря замыканиям внутри функционального компонента) и мемоизации (memoize(fn), день 6). Без понимания замыканий последующие темы курса будут восприниматься как магия, а не как логичное следствие лексической области видимости.

        +

        Частое заблуждение — путать замыкание с копированием значения: createMultiplier(n) не сохраняет копию n в момент вызова функции-результата, а держит живую ссылку на переменную n в её лексическом окружении. Классический пример — цикл for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100) } выведет 3, 3, 3, потому что все три колбэка держат один и тот же рюкзак с переменной i, которая к моменту вызова уже равна 3. Замена var на let создаёт отдельный рюкзак (и отдельную переменную i) для каждой итерации — колбэки выведут 0, 1, 2. Это задание 2 практики дня, и оно — лучший способ прочувствовать разницу на собственном опыте, а не поверить на слово.

        Читать: - learn.javascript.ru: Замыкание - MDN: Closures @@ -92,14 +95,17 @@

        Ловушки

      День 2 (Tue): this и контекст вызова

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Library System

      Теория

      Ключевое слово this в JavaScript определяется не местом объявления функции, а способом вызова. Существует четыре правила (в порядке приоритета): 1) new binding — this указывает на новый объект; 2) explicit binding — call/apply/bind задают this явно; 3) implicit binding — obj.method() привязывает this к obj; 4) default binding — в strict mode this равен undefined, иначе window.

      Потеря контекста — частая ошибка: const fn = obj.handleClick; btn.addEventListener('click', fn) передаёт функцию без объекта, и this внутри станет undefined. Решение — bind: fn.bind(obj) или стрелочная обёртка () => obj.handleClick(). Методы call и apply вызывают функцию немедленно с заданным this; bind возвращает новую функцию с навсегда привязанным контекстом.

      Стрелочные функции не имеют собственного this — они берут this из окружающего лексического scope. Это удобно для колбэков (map, setTimeout), но делает стрелочные функции плохими методами объектов. В strict mode default binding безопаснее — случайная привязка к window исчезает.

      +

      Удобная мысленная модель — бейдж сотрудника, а не имя, зашитое в паспорт: this — это не свойство самой функции, а бейдж, который функция получает в момент вызова в зависимости от того, как её позвали. Одна и та же функция greet даст разный this, если её вызвать как user.greet() (бейдж «user»), через greet.call(otherUser) (бейдж «otherUser») или просто greet() без объекта (бейдж не выдан — undefined в strict mode).

      +

      Понимание this критично для следующих двух дней недели: прототипы и классы (class и extends) целиком построены на корректной передаче this через цепочку конструкторов, а super() внутри дочернего класса — по сути явная передача бейджа от родителя к потомку. Позже, при работе с обработчиками событий DOM, потеря this — одна из самых частых причин багов уровня «функция вызвалась, но упала с Cannot read property of undefined».

      +

      Частое заблуждение — думать, что this определяется тем, где объявлена функция (как в замыканиях). На самом деле место объявления не влияет на this вообще — только способ вызова. Пример: const handleClick = obj.handleClick; button.addEventListener('click', handleClick) — внутри handleClick при клике this будет указывать на сам button (implicit binding через слушателя события), а не на obj, как ожидал бы новичок, глядя на исходное место объявления метода. Именно это несоответствие ожиданий — суть задания 2 практики: исправить потерю контекста через bind.

      Читать: - learn.javascript.ru: Методы привязки контекста - learn.javascript.ru: Справка по оператору this @@ -138,7 +144,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      
       cd learning-log/week-09
      @@ -150,14 +156,17 @@ 

      Git

      День 3 (Wed): Прототипы и наследование

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Library System

      Теория

      Наследование в JavaScript реализовано через цепочку прототипов, а не через классы в классическом ООП-смысле. Каждый объект имеет внутреннюю ссылку [[Prototype]] (доступна через Object.getPrototypeOf или устаревшее __proto__). При обращении к свойству движок ищет его на самом объекте, затем на прототипе, затем на прототипе прототипа — до null.

      Функции-конструкторы создают объекты через new: new Person('Anna') создаёт объект, привязывает this и устанавливает [[Prototype]] равным Person.prototype. Методы размещают на prototype, чтобы все экземпляры делили одну функцию, а не копировали её. Object.create(proto) создаёт объект с заданным прототипом без конструктора — чистый способ наследования.

      instanceof проверяет, есть ли Constructor.prototype в цепочке прототипов объекта — это не проверка «типа» в смысле TypeScript. hasOwnProperty отличает собственные свойства от унаследованных. Классы ES6 (class Person) — синтаксический сахар над этой же моделью; typeof Person === 'function'. Никогда не модифицируй Array.prototype или Object.prototype в production — это ломает чужой код.

      +

      Мысленная модель прототипной цепочки — библиотека с этажами: если нужной книги (свойства) нет на твоей полке (собственный объект), библиотекарь поднимается на этаж выше (прототип) и ищет там, потом ещё выше, и так до последнего этажа (Object.prototype), после которого выше уже ничего нет (null). Поиск свойства в JavaScript устроен именно так — не копированием данных между объектами, а делегированием запроса вверх по цепочке.

      +

      Эта модель объясняет, почему методы размещают на prototype, а не создают заново в каждом экземпляре: 1000 объектов Person не хранят 1000 копий функции greet — все они делегируют вызов одному и тому же методу на Person.prototype, экономя память. Понимание прототипов готовит к завтрашним классам ES6 (class — это просто удобный синтаксис поверх той же модели) и объясняет, почему typeof MyClass === 'function' — классы в JS остаются функциями под капотом.

      +

      Частое заблуждение — думать, что instanceof проверяет «настоящий тип» объекта, как в строго типизированных языках: на самом деле obj instanceof Person лишь проверяет, встречается ли Person.prototype где-то в цепочке прототипов obj, и это можно подделать через Object.create. Конкретный пример из практики дня: Student, созданный через Object.create(Person.prototype), пройдёт проверку student instanceof Person, даже если ты никогда явно не писал «Student наследует Person» — прототипная цепочка это единственный источник истины, а не namespace или декларация типа.

      Читать: - learn.javascript.ru: Прототипное наследование - learn.javascript.ru: F.prototype @@ -196,7 +205,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

      Git

      
       cd learning-log/week-09
      @@ -208,14 +217,17 @@ 

      Git

      День 4 (Thu): Классы ES6+

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Library System

      Теория

      Синтаксис class в ES6+ делает прототипное наследование читаемым. Класс объявляется как class TodoItem { constructor(title) { ... } toggle() { ... } }. Методы автоматически попадают на prototype. extends связывает прототипы дочернего и родительского классов, а super() в конструкторе вызывает родительский конструктор — без этого this в дочернем классе недоступен.

      Статические методы (static fromJSON(obj)) принадлежат самому классу, а не экземплярам — удобны для фабрик и утилит. Геттеры и сеттеры (get isOverdue()) выглядят как свойства, но вычисляются при обращении. С ES2022 приватные поля #id дают настоящую инкапсуляцию: к ним нельзя обратиться снаружи, в отличие от конвенции _id.

      Когда выбирать class, а когда factory + closure? Класс хорош для сущностей с общим прототипом и иерархией (Book extends Media). Factory с замыканием — для объектов с приватным состоянием без наследования. Под капотом class всё равно функция с prototypetypeof TodoItem === 'function'.

      +

      Мысленная модель — класс это чертёж (blueprint), а объект — конкретное здание, построенное по этому чертежу: чертёж описывает, какие комнаты (свойства) и какие двери (методы) будут в каждом здании, но жить в самом чертеже нельзя — нужно создать экземпляр через new. extends — это чертёж, который берёт за основу другой чертёж и добавляет к нему этаж, а super() — обязательный вызов «построй сначала базовый этаж по родительскому чертежу», без которого верхний этаж не может опираться ни на что.

      +

      Классы становятся рабочим инструментом для всего оставшегося курса: домены проекта «Библиотека» (Book, Member, Library) и, позже, доменные модели в TypeScript и React будут использовать либо классы, либо похожие по духу объектно-ориентированные структуры данных. Приватные поля #id — это первый шаг к пониманию инкапсуляции, который в TypeScript (неделя 10) получит ещё более строгую форму через модификаторы доступа.

      +

      Частое заблуждение — считать конвенцию _id (подчёркивание) настоящей приватностью: это лишь договорённость между разработчиками, и снаружи класса obj._id прекрасно читается и перезаписывается. Приватное поле #id, в отличие от этого, физически недоступно снаружи — попытка обратиться к obj.#id вне класса вызовет SyntaxError уже на этапе разбора кода, а не просто «плохой тон». Задание 4 практики («Private #id в классе») — шанс почувствовать разницу между «не трогай, пожалуйста» и «невозможно тронуть».

      Читать: - learn.javascript.ru: Класс - learn.javascript.ru: Наследование классов @@ -254,7 +266,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

      Git

      
       cd learning-log/week-09
      @@ -266,14 +278,17 @@ 

      Git

      День 5 (Fri): Паттерны проектирования

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Library System

      Теория

      Паттерны проектирования — проверенные решения типовых задач в архитектуре кода. Observer (Pub-Sub) отделяет источник событий от подписчиков: store вызывает emit('change', data), а UI подписывается через on('change', render). Компоненты не знают друг о друге напрямую — слабая связанность упрощает рефакторинг. EventEmitter на 50 строк — отличная учебная реализация.

      Module pattern (в ES modules — через export/import) инкапсулирует детали реализации: наружу видны только публичные функции. Strategy позволяет подменять алгоритм (сортировка byDate / byTitle) без ветвления if/else в клиентском коде — стратегия передаётся как функция. Factory (createNotification('error', msg)) скрывает создание объектов за единым интерфейсом.

      Singleton гарантирует один экземпляр (например, глобальный store), но усложняет тестирование и создаёт скрытое глобальное состояние — используй осознанно. MVC/MVP разделяют Model (данные), View (DOM) и Controller (логика) — твой Todo уже движется в эту сторону. Главное правило: не применяй паттерн ради паттерна в проекте на 50 строк.

      +

      Мысленная модель Observer — подписка на рассылку новостей: издатель (store) не знает лично каждого подписчика, он просто публикует событие в общий канал, а все, кто подписан, получают уведомление и решают сами, что с ним делать. Это радикально отличается от прямого вызова updateUI() внутри store — при таком подходе store пришлось бы знать обо всех частях UI, которые на него завязаны, и любое изменение интерфейса требовало бы правки store.

      +

      Наблюдатель, который ты реализуешь сегодня вручную (EventEmitter на 50 строк), — тот же принцип, что лежит в основе React: изменение state вызывает ререндер подписанных компонентов, а не императивный вызов render() из логики данных. Понимание паттернов на этом уровне избавляет от ощущения «магии» при первой встрече с useState и useEffect на неделе 11.

      +

      Частое заблуждение — начинать проектирование с вопроса «какой паттерн тут применить», а не «какая проблема связанности у меня есть». Паттерн — это название для решения, которое уже интуитивно напрашивается, а не чек-лист для внедрения ради резюме. Конкретный пример: если Store и View общаются напрямую через прямые вызовы методов друг друга, замена View (например, консольный вывод вместо DOM) потребует переписать Store — а с Observer Store продолжит работать без единой правки, просто у него появится другой подписчик. Это и есть цель задания 5 — «Рефакторинг Todo: Store + View + Controller», где связанность должна снизиться измеримо.

      Читать: - patterns.dev: Observer Pattern - patterns.dev: Module Pattern @@ -324,14 +339,18 @@

      Git

      День 6 (Sat): Функциональные приёмы

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Library System

      Теория

      Функциональное программирование в JavaScript — набор приёмов, делающих код предсказуемым. Чистая функция (pure function) при одинаковых аргументах всегда возвращает одинаковый результат и не вызывает побочных эффектов (не мутирует внешние переменные, не пишет в DOM). map, filter, reduce — примеры функций высшего порядка (HOF): они принимают функцию как аргумент и абстрагируют обход коллекции.

      Композиция объединяет маленькие функции в конвейер: pipe(validate, normalize, save)(input) читается слева направо, compose — справа налево. Каррирование превращает add(a, b) в add(a)(b) — полезно для частичного применения (filterBy('status', 'active')). Иммутабельность достигается через spread и structuredClone вместо прямой мутации.

      Рекурсия элегантна для деревьев и вложенных структур, но глубокая рекурсия упрётся в лимит стека (stack overflow). Для горячих путей предпочитай итерацию. memoize(fn) кэширует результаты чистой функции по аргументам — классический приём оптимизации. Referential transparency означает: можно заменить вызов функции её результатом без изменения поведения программы.

      +

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

      +

      Композиция (pipe/compose) и иммутабельность станут ежедневной практикой в React: обновление state через setState(prev => ({...prev, field: value})) — это иммутабельный апдейт, а селекторы данных обычно строятся именно как композиция маленьких чистых функций. Понимание рекурсии готовит к работе с деревьями — DOM-деревом, деревом компонентов React, вложенными комментариями или категориями.

      +

      Частое заблуждение — считать, что map/filter мутируют исходный массив: на самом деле оба метода возвращают новый массив, оставляя оригинал нетронутым — в отличие от push, splice или прямого присваивания по индексу, которые мутируют исходные данные. Конкретный пример риска рекурсии — глубоко вложенное дерево комментариев на 10000 уровней: рекурсивный обход упадёт с RangeError: Maximum call stack size exceeded, тогда как итеративный вариант со своим стеком (массивом) отработает без проблем — это стоит проверить в задании 5 практики на factorial(100) и увидеть реальный предел.

      +

      Тай-брейк между чистотой и производительностью решается прагматично: если функция вызывается редко (обработчик клика), пиши максимально чистой; если в горячем цикле рендера тысяч элементов — допустима контролируемая мутация локальной копии внутри функции, при условии что наружу она всё равно отдаёт новый объект и не трогает входные аргументы.

      Читать: - learn.javascript.ru: Каррирование - MDN: Array.prototype.reduce() @@ -370,7 +389,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      
       cd learning-log/week-09
      @@ -382,14 +401,17 @@ 

      Git

      День 7 (Sun): Рефакторинг и code quality

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Library System

      Теория

      Качество кода определяется не только работоспособностью, но и читаемостью, поддерживаемостью и предсказуемостью. SOLID в JavaScript-практике чаще всего сводится к двум принципам: Single Responsibility (один модуль — одна задача: api.js не рендерит DOM) и Dependency Inversion (высокоуровневый код зависит от абстракций, а не от конкретных реализаций). DRY (Don't Repeat Yourself) полезен, но иногда явное дублирование лучше преждевременной абстракции (правило WET — Write Everything Twice).

      ESLint ловит ошибки до runtime: неиспользуемые переменные, потерянные await, проблемы с ==. Prettier унифицирует форматирование — споры о пробелах исчезают. JSDoc документирует публичный API без TypeScript: @param {string} url, @returns {Promise<User>}. Это мост к строгой типизации на следующей неделе.

      ADR (Architecture Decision Record) — короткий документ «почему выбрали Store + Observer, а не один монолитный файл». Code review checklist: понятные имена, нет скрытых side effects, ошибки обработаны, модули имеют чёткие границы. Подготовка к TypeScript — явные контракты функций через JSDoc или .ts файлы.

      +

      Мысленная модель качества кода — не «идеальный» код с первой попытки, а сад, который регулярно пропалывают: рефакторинг — не разовое событие перед дедлайном, а постоянная практика вычищения дублирования, неясных имён и скрытых побочных эффектов по мере роста кодовой базы. Инструменты вроде ESLint и Prettier автоматизируют часть этой прополки, освобождая внимание для более важных архитектурных решений.

      +

      Привычка писать явные контракты (через JSDoc сегодня, через TypeScript — уже на следующей неделе) — прямая подготовка к строгой типизации: @param {string} url и @returns {Promise<User>} в JSDoc почти дословно превратятся в сигнатуру function fetchUser(url: string): Promise<User> в TypeScript. Тот, кто честно документирует функции сейчас, столкнётся с TypeScript не как с новым языком, а как с формализацией того, что он и так уже держал в голове.

      +

      Частое заблуждение — воспринимать DRY как абсолютное правило «никогда не повторяй код»: две функции, которые сейчас выглядят одинаково, но описывают разные бизнес-смыслы (например, валидация email пользователя и валидация email в форме подписки на рассылку), могут начать расходиться по мере развития продукта — преждевременное объединение их в одну общую функцию создаст ненужную связанность. Правило WET («write everything twice») напоминает: дай коду повториться два раза, и только на третьем повторении абстрагируй — это здравый компромисс, который стоит внести в ADR из задания 5 практики дня.

      Читать: - JSDoc reference - ESLint: Getting Started @@ -428,7 +450,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

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

      +

      Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

      Git

      
       cd learning-log/week-09
      diff --git a/docs/w/10.html b/docs/w/10.html
      index 752c7ec..4d2fe85 100644
      --- a/docs/w/10.html
      +++ b/docs/w/10.html
      @@ -22,14 +22,17 @@
       
       

      День 1 (Mon): Введение в TypeScript

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Typed API Client

      Теория

      TypeScript — это надмножество JavaScript со статической системой типов. Код пишется в .ts (или .tsx для JSX), компилируется компилятором tsc в обычный JavaScript, который выполняется в браузере или Node.js. Типы существуют только на этапе разработки и стираются при компиляции — в runtime никакой проверки типов нет. Зато IDE и компилятор ловят ошибки до запуска: опечатки в свойствах, неверные аргументы, забытые null.

      Установка: npm init -y, npm i -D typescript, npx tsc --init создаёт tsconfig.json. Ключевые опции: strict: true (включает все строгие проверки), target (версия JS на выходе), module (система модулей), outDir и rootDir. Базовые типы: string, number, boolean, null, undefined, bigint, symbol. Аннотация явная: let name: string = 'Anna', но чаще полагайся на вывод типов (inference): const count = 0 → TypeScript сам определит number.

      Команда npx tsc --noEmit проверяет типы без генерации файлов — удобно в CI. Разница .ts и .tsx: JSX-синтаксис допустим только в .tsx. Скрипт "build": "tsc" в package.json автоматизирует компиляцию, "dev": "tsc --watch" пересобирает при каждом сохранении.

      +

      Хорошая мысленная модель TypeScript — строительные леса вокруг здания: леса (типы) помогают безопасно и быстро строить, показывают, где не хватает опоры, но к моменту сдачи объекта (компиляции в JS) их полностью убирают — в готовом здании (браузере) лесов уже нет, только сам дом. Именно поэтому в runtime нет проверки типов: interface User не существует после компиляции, это чисто инструмент разработки, а не часть исполняемой программы.

      +

      Эта неделя — фундамент для всего оставшегося курса: React-компоненты, их props, состояние и API-слои в дальнейшем описываются практически исключительно на TypeScript, и большинство современных вакансий junior-frontend разработчика требуют именно TS, а не чистый JS. Инвестиция в понимание типов сейчас окупится кратно уже на неделе 11.

      +

      Частое заблуждение — думать, что TypeScript «медленнее» JavaScript в исполнении: это неверно, поскольку типы стираются до запуска, и скомпилированный .js-файл работает ровно с той же скоростью, что и написанный вручную JS. Единственная «цена» TypeScript — время компиляции (tsc) перед запуском, а не runtime-производительность. Конкретный пример пользы: function add(a: number, b: number) { return a + b }, вызванная как add('2', '3'), немедленно подсветится редактором как ошибка ещё до сохранения файла — в чистом JS та же ошибка обнаружилась бы только в runtime как склейка строк '23' вместо ожидаемого 5, и такую опечатку легко пропустить в задании 4 практики («исправь все ошибки компиляции»).

      Читать: - TypeScript: Getting Started - learn.javascript.ru: Типы @@ -80,14 +83,17 @@

      Git

      День 2 (Tue): Типы, union, literal, any

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Typed API Client

      Теория

      Union types объединяют несколько типов: string | number означает «или строка, или число». Literal types сужают множество до конкретных значений: type Theme = 'light' | 'dark' — не любая строка, а ровно два варианта. TypeScript не даст присвоить 'blue', если тип допускает только 'light' | 'dark'. Это основа для моделирования состояний и флагов.

      any отключает проверку типов — «дыра» в системе, через которую ошибки просачиваются обратно в runtime. Избегай any; вместо него используй unknown — тип «что-то есть, но мы не знаем что». С unknown нельзя ничего делать, пока не сузишь тип через typeof, in или type guard. Discriminated union добавляет общее поле-дискриминатор: { ok: true, data: T } | { ok: false, error: string } — switch по ok сужает тип в каждой ветке.

      as const делает объект readonly с literal-типами: const STATUS = { LOADING: 'loading' } as const. Тип never означает «недостижимо» — полезен в exhaustive switch: если добавишь новый вариант union, компилятор укажет на непокрытую ветку. Пользовательские type guards: function isUser(x: unknown): x is User — явный контракт сужения.

      +

      Мысленная модель union type — меню с ограниченным выбором, а не открытый вопрос «что хочешь съесть»: type Theme = 'light' | 'dark' — это меню из двух блюд, и компилятор физически не позволит «заказать» 'blue', потому что такого пункта нет. Это резко отличается от обычного string, который допускает любую строку — как меню без ограничений, где легко случайно заказать несуществующее блюдо и получить ошибку уже на кухне (в runtime).

      +

      Discriminated union и exhaustive switch — техника, которая будет использоваться постоянно при моделировании ответов API (успех/ошибка) и состояний UI (loading/success/error/empty, как в неделе 8) — только теперь эти состояния описываются типом, а не просто строкой, и компилятор гарантирует, что ни одна ветка не забыта. Это прямая подготовка к React, где состояния компонентов часто моделируются именно так.

      +

      Частое заблуждение — считать any и unknown взаимозаменяемыми, потому что оба «принимают что угодно». Разница принципиальна: any отключает все проверки для значения и всего, что из него получено (заражает код), а unknown требует явно сузить тип перед использованием — const x: unknown = data; x.toUpperCase() не скомпилируется, пока не добавишь if (typeof x === 'string'). Конкретный пример из практики: функция formatId(id: string | number), где внутри нужно явно проверить typeof id === 'string', прежде чем вызвать .toUpperCase() — иначе компилятор справедливо укажет, что у number такого метода нет.

      Читать: - Handbook: Everyday Types - Handbook: Narrowing @@ -126,7 +132,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      +

      Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

      Git

      
       cd learning-log/week-10
      @@ -150,14 +156,17 @@ 

      Ловушки

      День 3 (Wed): Interfaces и type aliases

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Typed API Client

      Теория

      Объекты в TypeScript описываются через interface или type. interface User { id: number; name: string; email?: string }email? опционален, его может не быть. readonly id: number запрещает переприсвоение после создания. Оба способа описывают форму объекта; различия тонкие: interface можно расширять (extends) и объединять (declaration merging), type гибче для union и mapped types.

      Расширение: interface Admin extends User { role: string } добавляет поля. Альтернатива — intersection: type Admin = User & { role: string }. Index signature [key: string]: string описывает объекты с динамическими ключами (словари, кэши). Для объектов предпочитай interface, для union и вычисляемых типов — type.

      Utility types из коробки: Readonly<T> делает все поля readonly, ReadonlyArray<T> — неизменяемый массив. В проекте заведи папку types/ с DTO (Data Transfer Objects): Todo, ApiResponse<T>, PaginationMeta. Типизированный api-модуль возвращает Promise<ApiResponse<Todo[]>> вместо «что-то пришло с сервера». Это контракт между слоями, который компилятор проверяет.

      +

      Мысленная модель interface/type — бланк договора между частями программы: до того как API-функция вернёт данные, интерфейс уже фиксирует, какие поля там будут и какого они типа — это контракт, который компилятор проверяет на каждом использовании, а не просто комментарий-пожелание. Если сервер изменит форму ответа, а DTO забудут обновить, TypeScript не поймает несоответствие с реальным JSON (он не знает про сеть), но зато любой код внутри приложения, который ожидает поля по старому контракту, останется согласованным и предсказуемым.

      +

      Явные DTO в отдельной папке types/ становятся особенно ценными на неделе 11: типы Todo, ApiResponse<T> из этой недели практически без изменений переедут в React-компоненты как типы props, избавляя от необходимости придумывать их заново. Хорошо спроектированные интерфейсы на этой неделе — это меньше работы на следующей.

      +

      Частое заблуждение — воспринимать interface и type как взаимоисключающий выбор «правильного» и «неправильного» инструмента: в большинстве junior-задач разница не критична, и команды чаще выбирают один стиль как конвенцию проекта, а не по глубоким техническим причинам. Единственный практический критерий, который стоит запомнить: если нужен union ('a' | 'b') или вычисляемый тип — это всегда type, поскольку interface такого не умеет; если нужно расширяемое описание формы объекта с возможностью declaration merging — чуть удобнее interface. Задание 4 практики («расширь User → Admin») — хороший повод попробовать оба варианта (extends и &) и увидеть, что результат идентичен.

      Читать: - Handbook: Objects - Handbook: Utility Types @@ -196,7 +205,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      
       cd learning-log/week-10
      @@ -208,14 +217,18 @@ 

      Git

      День 4 (Thu): Generics — основы

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Typed API Client

      Теория

      Generics (обобщения) позволяют писать функции и типы, работающие с разными типами, сохраняя связь между входом и выходом. function identity<T>(arg: T): T — тип возвращаемого значения совпадает с типом аргумента. Без generics пришлось бы писать отдельные функции для string, number, User или откатываться к any.

      Constraints ограничивают generic сверху: <T extends { id: number }> гарантирует, что у T есть поле id. keyof T даёт union всех ключей объекта, а indexed access T[K] — тип значения по ключу. Это основа для pluck(obj, 'name') с правильным return type. Generic defaults <T = string> задают тип по умолчанию, если параметр не указан.

      Практические применения: async function fetchJson<T>(url: string): Promise<T> типизирует ответ API; getItem<T>(key: string): T | null типизирует localStorage wrapper; groupBy<T, K extends string>(items, keyFn) группирует массив любых объектов. IDE будет подсказывать поля на результате fetchJson<User[]>(url) без ручных кастов.

      +

      Мысленная модель generic — форма для отливки, которая подходит под любой материал, но сохраняет форму: function identity<T>(arg: T): T — это форма, куда можно залить строку, число или объект, и на выходе гарантированно получить то же самое, что залили, а не что-то другое. Без generics пришлось бы либо копировать функцию под каждый тип материала, либо использовать any — и тогда форма перестаёт что-либо гарантировать, превращаясь в дырявое ведро.

      +

      Generics — пожалуй, самая мощная идея TypeScript для junior-разработчика, потому что она напрямую используется в React: useState<Todo[]>([]), useRef<HTMLInputElement>(null), useContext<AuthContextType> — все эти хуки на неделе 11 и позже являются generic-функциями. Тот, кто разобрался с fetchJson<T> сегодня, не удивится синтаксису useState<T> через несколько недель.

      +

      Частое заблуждение — путать generic-параметр <T> с типом any, считая, что раз буква T может быть «чем угодно», значит проверки нет вообще. На самом деле после того, как T определён при вызове (fetchJson<User>(url)), TypeScript отслеживает его строго во всей функции. Конкретный пример пользы: const user = await fetchJson<User>('/api/user') даёт автодополнение по полям user.name, user.email прямо в IDE — тогда как fetchJson('/api/user') без указания типа вернёт unknown, и обратиться к .name без явной проверки не получится, что стоит заметить в задании 7 практики («проверь inference в IDE»).

      +

      Ещё один полезный приём — generic по умолчанию: class ApiClient<T = unknown> позволяет использовать new ApiClient() без явного указания типа, если он не критичен в конкретном месте, но при необходимости уточнить его как new ApiClient<User>(). Это балансирует гибкость и строгость, не заставляя писать <T> там, где тип и так очевиден из контекста.

      Читать: - Handbook: Generics - Handbook: Keyof Types @@ -254,7 +267,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      +

      Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

      Git

      
       cd learning-log/week-10
      @@ -266,14 +279,17 @@ 

      Git

      День 5 (Fri): Функции, utility types, enums

      -

      Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Typed API Client

      Теория

      Типизация функций в TypeScript охватывает параметры, возвращаемое значение и перегрузки. Optional параметры (name?: string), значения по умолчанию (size = 'md') и rest (...args: number[]) типизируются явно. Return type можно вывести (inference), но явный return полезен для публичного API — компилятор проверит, что все ветки возвращают заявленный тип.

      Utility types трансформируют существующие типы: Partial<T> делает все поля опциональными (удобно для update DTO), Pick<T, 'title' | 'done'> выбирает подмножество полей, Omit<T, 'id'> исключает поля, Record<Keys, Type> строит объект с заданными ключами. Пример: type UpdateTodo = Partial<Pick<Todo, 'title' | 'done'>> — обновление только разрешённых полей.

      enum в modern TypeScript уступает union of literals: const STATUS = { LOADING: 'loading', SUCCESS: 'success' } as const; type Status = typeof STATUS[keyof typeof STATUS]. Такой подход лучше tree-shaking и не генерирует лишний JS. Function overloads задают несколько сигнатур для одной реализации. Parameters<T> и ReturnType<T> извлекают типы из существующих функций. Оператор satisfies (TS 4.9+) проверяет тип, сохраняя literal inference.

      +

      Мысленная модель utility types — конструктор Lego, где из готовых кубиков (существующих типов) собираются новые формы без ручной лепки с нуля: Partial<Todo> берёт тип Todo и говорит «все поля теперь опциональны», Pick<Todo, 'title'> — «оставь только эту деталь», Omit<Todo, 'id'> — «убери эту деталь, остальное оставь». Это избавляет от ручного дублирования почти идентичных интерфейсов для create/update/read версий одной и той же сущности.

      +

      Эти приёмы напрямую переносятся в API-слои React-приложений: типичный паттерн type CreateTodoDto = Omit<Todo, 'id' | 'createdAt'> (сервер сам генерирует id и дату) встречается в подавляющем большинстве реальных проектов, и понимание его сегодня избавит от копипасты интерфейсов позже. Замена enum на as const объект — тоже не просто вкусовщина: enum исторически генерирует дополнительный JS-код при компиляции, тогда как as const полностью стирается, что мельче бандл и лучше tree-shaking для production-сборки на Vite (день 6 этой недели).

      +

      Частое заблуждение — думать, что Partial<T> делает объект необязательным целиком, а не каждое поле по отдельности: Partial<Todo> всё ещё требует объект (не undefined), просто каждое его свойство (title, done) можно опустить. Конкретный пример из практики: type UpdateTodo = Partial<Pick<Todo, 'title' | 'done'>> описывает ровно то, что можно менять при PATCH-запросе — не весь Todo целиком и не произвольные поля, а только title и done, оба опционально.

      Читать: - Handbook: Utility Types - Handbook: More on Functions @@ -324,14 +340,18 @@

      Git

      День 6 (Sat): TS + React setup

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Typed API Client

      Теория

      Vite — современный инструмент сборки для фронтенда с мгновенным dev-сервером и HMR (Hot Module Replacement). Создание React + TypeScript проекта: npm create vite@latest my-app -- --template react-ts. Структура: src/main.tsx — точка входа, App.tsx — корневой компонент, vite-env.d.ts — типы Vite. TypeScript настроен из коробки.

      Props React-компонента типизируются через interface: interface ButtonProps { label: string; onClick: () => void; variant?: 'primary' | 'secondary'; disabled?: boolean }. Современная рекомендация — обычная функция function Button({ label, onClick }: ButtonProps), а не React.FC (устаревший паттерн с неявным children). React.ReactNode описывает всё, что можно отрендерить (строки, числа, элементы, массивы, null). React.ReactElement — конкретно JSX-элемент.

      Vite конфигурируется в vite.config.ts; path aliases настраиваются и в tsconfig, и в vite. React Strict Mode в dev намеренно вызывает двойной render компонентов, чтобы выявить побочные эффекты — это нормально и не баг. Команды: npm run dev (разработка), npm run build (production-сборка с проверкой типов).

      +

      Мысленная модель Vite — конвейер быстрой сборки с горячей заменой деталей на ходу: вместо того чтобы каждый раз пересобирать весь автомобиль (bundle) с нуля при малейшей правке, HMR подменяет только изменённую деталь (модуль) прямо во время движения, не перезагружая всю страницу и сохраняя текущее состояние компонентов (например, введённый в форму текст).

      +

      Всё, что изучалось эту неделю — интерфейсы, generics, utility types — сходится именно здесь: типизация props компонента — первое место, где TypeScript встречается с React напрямую, и качество этого стыка определяет, насколько безопасно можно будет рефакторить компоненты в дальнейшем на неделе 11. Хорошо типизированный ButtonProps — это защита от передачи onClick={someString} по ошибке, которую поймает компилятор, а не пользователь в браузере.

      +

      Частое заблуждение — использовать React.FC<Props> для типизации компонентов по старой памяти из туториалов пятилетней давности: современное сообщество React рекомендует обычную функцию с типизированными параметрами (function Button(props: ButtonProps)), поскольку React.FC неявно добавляет children всем компонентам (даже тем, где children не предполагается) и хуже работает с generic-компонентами. Конкретный пример из задания 4 практики — Card с children: React.ReactNode: ReactNode покрывает всё, что React способен отрендерить (строка, число, JSX, массив, null), тогда как ReactElement — только конкретный JSX-элемент.

      +

      Ещё одна деталь, которая экономит время: файлы Vite с JSX обязаны иметь расширение .tsx, а не .ts — компилятор попросту не поймёт синтаксис <div> внутри .ts-файла и попытается интерпретировать угловые скобки как generic-приведение типов, выдав криптичную ошибку. Эта путаница — частая причина первых «непонятных» ошибок при переносе логики из .ts в компонент.

      Читать: - React TypeScript Cheatsheet: Setup - Vite Guide @@ -370,7 +390,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      +

      Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

      Git

      
       cd learning-log/week-10
      @@ -382,14 +402,18 @@ 

      Git

      День 7 (Sun): Миграция и strict mode

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Typed API Client

      Теория

      Миграция существующего JS-проекта на TypeScript может быть постепенной. В tsconfig.json включи allowJs: true — компилятор будет проверять .js файлы рядом с .ts. checkJs: true добавляет проверку типов в JS через JSDoc-аннотации. Переименовывай файлы по одному: api.jsapi.ts, исправляй ошибки, коммить.

      Типы для npm-пакетов без встроенной типизации лежат в DefinitelyTyped: @types/react, @types/node. Declaration files (.d.ts) описывают форму JS-модуля без реализации — нужны для legacy-библиотек. Path aliases в tsconfig ("@/*": ["src/*"]) и в vite.config.ts сокращают импорты: import { Button } from '@/components/Button'.

      Строгие опции поверх strict: noUncheckedIndexedAccess добавляет | undefined к arr[i] и obj[key] — заставляет проверять границы. exactOptionalPropertyTypes различает «поле отсутствует» и «поле равно undefined». Документируй решения tsconfig в docs/typescript.md — будущий ты (и команда) скажут спасибо.

      +

      Мысленная модель постепенной миграции — замена деталей в работающем автомобиле на ходу, а не разбор его на запчасти в гараже на неделю: allowJs: true позволяет .ts и .js файлам существовать бок о бок и импортировать друг друга, пока файлы переименовываются по одному (api.jsapi.ts), а не одним гигантским коммитом, который рискует сломать всё сразу и который невозможно нормально код-ревьюить.

      +

      Этот навык напрямую пригодится в реальной работе: подавляющее большинство существующих production-кодовых баз в индустрии — это не написанный с нуля на строгом TypeScript проект, а именно постепенно мигрирующий JS-код, и умение делать это безопасно, файл за файлом, ценится не меньше умения писать типы с нуля. noUncheckedIndexedAccess — одна из самых важных строгих опций, о которой часто не знают даже после нескольких месяцев с TypeScript.

      +

      Частое заблуждение — считать, что strict: true уже покрывает все возможные проверки безопасности типов: на самом деле noUncheckedIndexedAccess не входит в strict по историческим причинам обратной совместимости, и без неё const item = arr[999] в массиве из трёх элементов будет типизирован как обычный элемент, а не T | undefined, хотя в runtime там окажется undefined — источник классических «Cannot read property of undefined» уже после успешной компиляции. Задание 3 практики («включи noUncheckedIndexedAccess — исправь новые ошибки») специально показывает, сколько скрытых мест в коде полагались на удачу при обращении по индексу.

      +

      Не стоит включать все строгие опции разом «для галочки»: каждая новая опция может вскрыть десятки мест в существующем коде, требующих исправления, и разумнее включать их по одной, коммитить исправления отдельно и двигаться к максимальной строгости постепенно — это тот же принцип итеративной миграции, что и с самим переходом с JS на TS.

      Читать: - Handbook: Migrating from JavaScript - DefinitelyTyped @@ -428,7 +452,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      
       cd learning-log/week-10
      diff --git a/docs/w/11.html b/docs/w/11.html
      index 0d1aacb..db7b01b 100644
      --- a/docs/w/11.html
      +++ b/docs/w/11.html
      @@ -22,14 +22,17 @@
       
       

      День 1 (Mon): Введение в React и JSX

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к React Todo

      Теория

      React — библиотека для построения пользовательских интерфейсов на основе компонентов. Компонент — это JavaScript-функция (или класс), которая принимает props и возвращает описание UI. React берёт это описание и обновляет реальный DOM эффективно через Virtual DOM и reconciliation. Философия React: UI = f(state) — интерфейс является функцией от состояния.

      JSX — синтаксическое расширение, которое выглядит как HTML, но компилируется в вызовы React.createElement. Правила JSX отличаются от HTML: className вместо class, htmlFor вместо for, все теги закрываются (<img />, <br />). В фигурных скобках {expression} встраивается любое JavaScript-выражение: переменные, вызовы функций, тернарные операторы.

      Компоненты именуются в PascalCase (Header, TodoItem), а props — в camelCase. JSX автоматически экранирует строки — вставка пользовательского текста безопасна от XSS. Компонент должен возвращать один корневой элемент; если нужно несколько соседних без обёрточного <div>, используй Fragment: <>...</>. Не вызывай компоненты как обычные функции Header() — только через JSX <Header />, иначе React не отследит жизненный цикл и hooks.

      +

      Мысленная модель React — театр теней, где ты не двигаешь фигурки на экране руками (не пишешь document.querySelector и .innerHTML вручную), а просто описываешь, как должна выглядеть сцена при текущем состоянии сюжета — React сам разбирается, какие фигурки подвинуть, а какие оставить на месте. UI = f(state) означает: дай мне текущее состояние — и я построю (или перестрою) весь экран заново на бумаге (Virtual DOM), а дальше сравню с предыдущей версией и внесу в реальный DOM только конкретные изменения.

      +

      Этот декларативный подход — причина, по которой почти весь современный фронтенд использует React или похожие библиотеки: он снимает с разработчика необходимость вручную отслеживать, какие части DOM устарели после изменения данных, — раньше это была одна из главных причин багов в jQuery-подобном коде. Всё, что изучалось на неделях 8–9 (async, замыкания, паттерн Observer), напрямую готовило именно к этой модели: React-компонент — это, по сути, функция, подписанная на изменения state через встроенный Observer-механизм.

      +

      Частое заблуждение новичков — вызывать компонент как обычную функцию (Header()) вместо JSX (<Header />), особенно когда нужно «просто получить разметку». Разница критична: только вызов через JSX регистрирует компонент в дереве React с собственным местом для hooks и состояния; прямой вызов функции полностью ломает эту связь, и hooks внутри такого компонента либо упадут с ошибкой, либо будут работать непредсказуемо. Задание 3 практики («вынеси Header, Footer, Hero в отдельные файлы») стоит сразу делать с привычкой использовать JSX-синтаксис, а не вызовы функций.

      Читать: - react.dev: Describing the UI - react.dev: Writing Markup with JSX @@ -80,14 +83,17 @@

      Git

      День 2 (Tue): Props и композиция

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к React Todo

      Теория

      Props (properties) — единственный способ передать данные от родителя к ребёнку в React. Props read-only: дочерний компонент не должен их мутировать. Это основа однонаправленного потока данных (one-way data flow): состояние живёт выше, данные текут вниз через props, события — вверх через callback-функции.

      Деструктуризация в сигнатуре делает код читаемым: function Button({ label, onClick, variant = 'primary' }) вместо props.label. Значения по умолчанию задавай прямо в деструктуризации. Специальный prop children — содержимое между открывающим и закрывающим тегами: <Card>Это children</Card>. Паттерн slot: Card рендерит children внутри своей разметки, а родитель решает, что туда положить.

      Spread props (<Input {...fieldProps} />) передаёт все свойства объекта разом — удобно, но осторожно: лишние props могут попасть на DOM-элемент и вызвать warning. Props drilling на 1–2 уровня — нормальная практика; Context (неделя 13+) понадобится при глубокой вложенности. В TypeScript каждый компонент получает interface XxxProps с явными типами.

      +

      Мысленная модель props — посылка с товаром, а не пульт дистанционного управления: родитель кладёт в посылку (props) всё, что нужно ребёнку для отображения, и отправляет её вниз, но не может через эту же посылку управлять ребёнком напрямую — единственный способ «получить обратную связь» от ребёнка — это положить в посылку функцию-callback (onClick), которую ребёнок вызовет, если что-то произойдёт. Информация всегда течёт по одному маршруту: данные — вниз, события — вверх.

      +

      Эта дисциплина односторонного потока данных станет критичной уже завтра при работе со списками и на день 5 этой недели, при подъёме состояния (lifting state up): как только в приложении появляется больше двух-трёх компонентов, обменивающихся данными, любое отклонение от «props вниз, callback вверх» превращает приложение в паутину сложно отслеживаемых связей. Паттерн children — первый шаг к композиции, которая в React предпочтительнее наследования компонентов.

      +

      Частое заблуждение — пытаться изменить props изнутри дочернего компонента, например props.disabled = true внутри Button: это не вызовет ошибку синтаксиса, но нарушит контракт React и приведёт к рассинхронизации между тем, что видит родитель, и тем, что реально происходит. Конкретный пример из задания 4 практики — композиция Card внутри Hero, где Hero передаёт в Card не данные напрямую, а готовый JSX через children, что позволяет Card оставаться полностью независимым от содержимого, которое в него положат.

      Читать: - react.dev: Passing Props to a Component - react.dev: Thinking in React @@ -126,7 +132,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

      +

      Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

      Git

      
       cd learning-log/week-11
      @@ -150,14 +156,17 @@ 

      Ловушки

      День 3 (Wed): Списки, keys и рендеринг

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к React Todo

      Теория

      Списки в React рендерятся через array.map(): каждый элемент массива превращается в JSX. React нужен атрибут key на элементе верхнего уровня в map — уникальный и стабильный идентификатор (обычно item.id). Key помогает reconciliation: React сопоставляет элементы между рендерами и обновляет только изменившиеся, а не пересоздаёт весь список.

      Использование индекса массива как key (key={index}) допустимо только для статических списков без reorder/delete. При удалении элемента из середины индексы сдвигаются — React перепутает компоненты, и state (например, фокус input) «переедет» к другому элементу. Всегда предпочитай key={todo.id}.

      Условный рендеринг: {isLoggedIn && <Dashboard />} (осторожно — 0 falsy и отрендерится как текст), тернарный {loading ? <Spinner /> : <List />}, early return if (!data) return null. Не вызывай компоненты как функции TodoItem(todo) — только <TodoItem todo={todo} />. Fragment с key нужен при map фрагментов: <Fragment key={id}>...</Fragment>.

      +

      Мысленная модель key — номерок в гардеробе, а не порядковое место в очереди: если ты сдал куртку под номерком 42, гардеробщик найдёт именно твою куртку, даже если перед тобой в очереди кто-то ушёл или встал новый человек — потому что номерок привязан к вещи, а не к позиции в очереди. Индекс массива в качестве key — это использование места в очереди вместо номерка: работает, пока никто не покидает очередь и не встаёт в середину, но ломается при малейшей перестановке.

      +

      Правильная работа со списками и keys — база, на которой строится практически весь остаточный курс: Todo-приложение этой недели, а позже любой список карточек, комментариев или элементов меню в реальных проектах будет опираться именно на эту механику reconciliation. Ошибки с key — одна из самых частых причин странных багов вроде «текст в input переехал не в ту строку после удаления элемента», которые сложно диагностировать, не зная про reconciliation.

      +

      Частое заблуждение — считать warning React про отсутствующий key просто стилистической придиркой линтера, которую можно проигнорировать. Конкретный пример: список из трёх задач с controlled input для редактирования названия, где key — это index; при удалении первой задачи React решит, что вторая задача (индекс 0) заменила первую, и переиспользует её DOM-узел вместе с локальным состоянием (например, фокусом или незасабмиченным текстом в поле), хотя данные (todo.id) на самом деле принадлежат другой задаче. Задание 7 практики («проверь: удаление средней задачи не ломает state остальных») — прямая проверка именно этого сценария.

      Читать: - react.dev: Rendering Lists - react.dev: Conditional Rendering @@ -196,7 +205,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      
       cd learning-log/week-11
      @@ -208,14 +217,17 @@ 

      Git

      День 4 (Thu): События и состояние (useState)

      -

      Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к React Todo

      Теория

      Интерактивность в React начинается с useState — hook, дающий компоненту «память». const [count, setCount] = useState(0) возвращает текущее значение и функцию обновления. Вызов setCount планирует ререндер компонента с новым значением. State — это снимок на момент рендера: если вызвать setCount(count + 1) три раза подряд в одном обработчике, счётчик увеличится на 1, не на 3. Для последовательных обновлений используй функциональную форму: setCount(c => c + 1).

      Обновления state должны быть иммутабельными: вместо todos.push(item) пиши setTodos([...todos, item]); вместо todo.done = truesetTodos(todos.map(t => t.id === id ? { ...t, done: true } : t)). React сравнивает ссылки — мутация не вызовет ререндер. Controlled input связывает <input value={text} onChange={e => setText(e.target.value)} /> — React state единственный источник правды для значения поля.

      Несколько useState предпочтительнее одного большого объекта state — проще обновлять отдельные поля. Derived values (счётчик активных задач) вычисляй из state при рендере, а не храни в отдельном useState. Batching: React объединяет несколько setState в одном обработчике события в один ререндер.

      +

      Мысленная модель useState — стикер на холодильнике, который React перечитывает перед каждым рендером, а не переменная, которую можно менять на лету: вызов setCount(5) не меняет count немедленно в текущей функции — он говорит React «на следующем рендере напиши на стикере 5», и только тогда компонент увидит новое значение. Именно поэтому console.log(count) сразу после setCount(count + 1) в том же обработчике покажет старое значение — стикер ещё не переписан.

      +

      Иммутабельные обновления state — не просто стилистическая рекомендация, а требование механизма React: reconciliation (день 3 этой недели) сравнивает ссылки на объекты между рендерами для оптимизации, и мутация todo.done = true не создаёт новую ссылку, поэтому React может решить, что ничего не изменилось, и пропустить ререндер, оставив UI визуально устаревшим при внутренне изменённых данных. Этот же принцип иммутабельности потребуется в Redux, Zustand и других state-менеджерах, которые встретятся дальше в карьере.

      +

      Частое заблуждение — думать, что несколько вызовов setState в одном обработчике происходят мгновенно и последовательно: setCount(count + 1); setCount(count + 1); setCount(count + 1) при count = 0 даст count = 1, а не 3, потому что все три вызова читают одно и то же значение count из замыкания текущего рендера (см. неделю 9 про замыкания — прямое применение той темы). Чтобы получить 3, нужна функциональная форма: setCount(c => c + 1) трижды — каждый вызов получает актуальное промежуточное значение. Это ключевая проверка в задании 1 практики («счётчик с useState»).

      Читать: - react.dev: State: A Component's Memory - react.dev: Adding Interactivity @@ -254,7 +266,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      
       cd learning-log/week-11
      @@ -266,14 +278,17 @@ 

      Git

      День 5 (Fri): Формы и подъём состояния

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к React Todo

      Теория

      Формы в React обрабатываются через событие onSubmit на <form> с обязательным e.preventDefault() — иначе браузер перезагрузит страницу. Подъём состояния (lifting state up) — ключевой паттерн: если два компонента (TodoList и FilterTabs) должны разделять данные, state поднимается к их ближайшему общему родителю (TodoApp). Родитель хранит todos и filter, детям передаёт данные и колбэки.

      Controlled components — стандарт для форм: значение input, textarea, select и checkbox полностью управляется React state. Uncontrolled (через ref) допустим для простых случаев, но controlled даёт полный контроль: валидация, disabled, сброс. Колбэки вниз: onToggle(id), onDelete(id), onFilterChange('active') — дочерний компонент сообщает родителю о действии, не меняя state напрямую.

      Валидация на клиенте: проверяй перед submit (пустая задача не добавляется), показывай ошибку рядом с полем. Атрибут name на input важен для autofill и семантики. Disabled кнопка submit при невалидной форме — простая и эффективная UX-защита. Enter в поле ввода сабмитит форму, если input внутри <form>.

      +

      Мысленная модель подъёма состояния — общий банковский счёт семьи вместо отдельных кошельков у каждого члена: если TodoList и FilterTabs хранили бы каждый свою копию списка задач или фильтра, они быстро разошлись бы в показаниях; подняв единственный «счёт» (state) к общему родителю TodoApp, оба компонента всегда видят одни и те же актуальные данные, просто получают их сверху как props.

      +

      Этот принцип — прямое следствие однонаправленного потока данных, изученного в день 2, и он же причина, по которой в больших приложениях появляются глобальные хранилища состояния (Context API, Redux, Zustand — темы будущих недель): по сути, они автоматизируют «подъём состояния» до уровня всего приложения, когда общий родитель для двух компонентов оказывается слишком далеко в дереве. Понимание lifting state up вручную — обязательный шаг перед тем, как эти инструменты станут осмысленными, а не «магическими коробками».

      +

      Частое заблуждение — забывать e.preventDefault() в обработчике onSubmit: без него браузер выполнит свою родную логику отправки формы — полную перезагрузку страницы, — и весь React state приложения сбросится, будто страница открыта заново. Конкретный пример из задания 2 практики: AddTodoForm должен не просто добавить задачу в массив, но и явно очистить своё поле ввода после сабмита — если это забыть, React аккуратно оставит в controlled input то значение, что было до сабмита, ведь состояние поля никто не сбросил.

      Читать: - react.dev: Reacting to Input with State - react.dev: Sharing State Between Components @@ -324,14 +339,17 @@

      Git

      День 6 (Sat): Стилизация и структура проекта

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к React Todo

      Теория

      Стилизация React-приложения начинается с организации, а не с выбора CSS-in-JS библиотеки. CSS Modules изолируют стили: import styles from './Button.module.css' и className={styles.primary} — классы уникальны на уровне файла, нет конфликтов имён. Условные классы удобно собирать через template literal или утилиту cn(...classes), которая фильтрует falsy-значения.

      Структура src/ по назначению: components/ui/ — переиспользуемые (Button, Card), components/todo/ — предметные, types/ — TypeScript-интерфейсы, hooks/ — custom hooks (позже), utils/ — чистые функции, data/ — mock-данные. Vite позволяет импортировать изображения как модули: import logo from './logo.svg' — URL подставится автоматически.

      Тёмная тема через CSS variables: в :root задай --bg: #fff; --text: #111, в .dark переопредели --bg: #111; --text: #fff. Переключение — class на <html> или корневом div, управляемый React state. prefers-color-scheme: dark в media query задаёт системную тему по умолчанию. Mobile-first: базовые стили для узкого экрана, @media (min-width: 768px) для расширения.

      +

      Мысленная модель CSS Modules — именные бейджи на конференции вместо простых имён на футболке: класс .primary в обычном CSS — это имя на футболке, которое может совпасть у двух незнакомых людей (двух компонентов) и вызвать путаницу (конфликт стилей); CSS Modules автоматически превращают .primary в уникальный .Button_primary__a3f9k, как персональный бейдж с номером — конфликт физически невозможен, даже если два файла независимо используют одно и то же короткое имя класса.

      +

      Продуманная структура папок (components/ui/, components/todo/, types/, hooks/, utils/) — не бюрократия, а прямая подготовка к росту проекта: как только в приложении становится больше 15–20 компонентов, плоская структура файлов в одной папке превращается в неразбираемый список, и рефакторинг структуры «на живую» гораздо дороже, чем следование конвенции с самого начала. CSS variables для темы — тот же принцип, что и useState для данных: единый источник истины (--bg, --text), который меняется в одном месте и автоматически применяется везде, где используется.

      +

      Частое заблуждение — реализовывать тёмную тему через дублирование всех компонентов или инлайновые проверки isDark ? '#111' : '#fff' в каждом месте, где нужен цвет: это плохо масштабируется и легко забыть при добавлении нового компонента. Конкретный пример из задания 5 практики: одна строка document.documentElement.classList.toggle('dark') вместе с заранее описанными CSS-переменными в :root и .dark переключает весь интерфейс разом, без единого условия внутри JSX компонентов — вся логика темы живёт в CSS, а React лишь переключает один класс.

      Читать: - Vite: Static Assets - CSS Modules — spec @@ -370,7 +388,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

      Git

      
       cd learning-log/week-11
      @@ -382,14 +400,17 @@ 

      Git

      День 7 (Sun): Сборка Todo App и деплой

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к React Todo

      Теория

      Завершение Todo App объединяет state, effects и production-сборку. useEffect — hook для синхронизации React state с внешним миром (localStorage, document.title, подписки). Для persist: useEffect(() => { localStorage.setItem('todos', JSON.stringify(todos)) }, [todos]) — сохраняй при каждом изменении. Начальное значение загружай через lazy init: useState(() => JSON.parse(localStorage.getItem('todos') ?? '[]')).

      Production-сборка: npm run build создаёт оптимизированный bundle в dist/, npm run preview проверяет его локально. Деплой на GitHub Pages, Netlify или Vercel — статический хостинг для SPA. Для GitHub Pages задай base в vite.config.ts (путь репозитория). Environment variables в Vite доступны только с префиксом VITE_ — они встраиваются в клиентский код и видны всем.

      React Strict Mode в dev вызывает двойной mount/unmount — это помогает найти missing cleanup в effects. Перед деплоем прогони Lighthouse: Performance, Accessibility, Best Practices. Escape Hatches (useEffect, useRef) — инструменты «выхода» из чистой модели React, когда нужна интеграция с браузерными API.

      +

      Мысленная модель useEffect — розетка, через которую компонент подключается к внешнему миру за пределами React (браузерное API, таймер, подписка, localStorage): React сам управляет своим внутренним миром (state, JSX), но для всего, что находится снаружи этой модели, нужен явный «провод» — эффект, который запускается после рендера и должен уметь отключиться (cleanup-функция), когда компонент размонтируется или зависимости меняются, — иначе розетка останется под напряжением без нужды (утечка памяти, лишние подписки).

      +

      Эта неделя завершает связку тем всего курса: async/await и Promise (неделя 8) применяются внутри useEffect для загрузки данных, замыкания (неделя 9) объясняют, почему эффект «видит» устаревшее значение state, если забыть указать зависимость в массиве [todos], а TypeScript (неделя 10) типизирует и сам todos, и то, что приходит из localStorage.getItem(). Деплой — финальный шаг, превращающий учебный проект в то, что можно показать в резюме и на собеседовании по ссылке, а не только скриншотом.

      +

      Частое заблуждение — использовать обычный useState(JSON.parse(localStorage.getItem('todos') ?? '[]')) без функции-инициализатора: такая запись выполняет JSON.parse и чтение localStorage при каждом рендере компонента, а не только при первом монтировании, что зря тратит ресурсы на большом списке задач. Ленивая инициализация useState(() => JSON.parse(...)) передаёт функцию, а не результат её вызова — React выполнит её ровно один раз, при первом рендере. Это стоит явно проверить в задании 2 практики дня, добавив временный console.log внутрь инициализатора и посчитав, сколько раз он сработает при обычном использовании приложения.

      Читать: - react.dev: Escape Hatches - react.dev: useEffect @@ -428,7 +449,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      
       cd learning-log/week-11
      diff --git a/docs/w/12.html b/docs/w/12.html
      index aca9e2d..f810f8d 100644
      --- a/docs/w/12.html
      +++ b/docs/w/12.html
      @@ -22,14 +22,18 @@
       
       

      День 78 (Пн): useState — память компонента

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к React Todo Pro

      Теория

      useState — фундаментальный hook React, дающий функциональному компоненту локальное состояние. При первом рендере React создаёт ячейку state; при последующих — возвращает сохранённое значение. setState не меняет переменную мгновенно — он планирует ререндер с новым значением. Поэтому console.log(count) сразу после setCount(5) покажет старое значение.

      Иммутабельные обновления обязательны: [...arr, item] для добавления, arr.filter(...) для удаления, arr.map(...) для изменения элемента. Прямая мутация (arr.push, obj.field = x) не вызовет ререндер, потому что ссылка на объект не изменилась. Lazy initialization useState(() => expensiveCalc()) вычисляет начальное значение только при первом рендере — важно для чтения localStorage.

      Функциональный апдейт setCount(c => c + 1) получает актуальное значение из очереди обновлений. Три таких вызова подряд дадут +3, в отличие от setCount(count + 1). State изолирован между экземплярами: два <Counter /> на странице имеют независимые счётчики. Несколько useState лучше одного объекта — проще обновлять и меньше риск случайной мутации.

      +

      Полезная мысленная модель: state — это не «переменная», а ячейка в скрытой памяти React, привязанная к позиции компонента в дереве рендеринга. Каждый рендер — это функция, вызванная заново, и все обычные переменные внутри неё создаются с нуля; только то, что явно объявлено через useState, «выживает» между вызовами. Отсюда и правило: count внутри тела компонента — это константа для конкретного рендера, «снимок» на момент вызова, а не текущее значение в реальном времени.

      +

      Это фундамент для всего, что будет дальше: useReducer, Context, внешние стейт-менеджеры (Redux, Zustand) — все они держатся на той же идее иммутабельных обновлений и рендера как чистой функции от state. Пример: если реализовать историю кликов через setHistory(h => [...h, Date.now()]), каждый вызов добавляет новый элемент, не трогая старые — из истории потом легко построить график или отменить последнее действие (undo), потому что прошлые снимки не испорчены мутацией.

      +

      Частое заблуждение новичков — считать, что setCount меняет count «здесь и сейчас», как обычное присваивание в императивном коде. На самом деле React только помечает компонент как «грязный» и планирует повторный вызов функции-компонента с новым значением; до этого момента в замыкании текущего обработчика count остаётся старым. Это объясняет, почему setCount(count + 1), вызванный трижды подряд в одном обработчике, использует одно и то же устаревшее значение count из замыкания — отсюда и важность функционального апдейта setCount(c => c + 1), который получает свежее значение из очереди, а не из замыкания.

      +

      На практике этого дня именно эта модель объясняет, почему Counter с тремя быстрыми кликами не «теряет» события, а ColorPicker корректно переключает тему даже при частых кликах — React гарантированно обработает каждое обновление очереди, даже если промежуточные значения не видны сразу в коде.

      Читать: - useState - react.dev: State: A Component's Memory @@ -90,14 +94,18 @@

      Ловушки


      День 79 (Вт): События и controlled components

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к React Todo Pro

      Теория

      Обработка событий в React похожа на DOM, но есть отличия. Атрибуты пишутся в camelCase: onClick, onChange, onSubmit. React использует Synthetic Events — обёртку над нативными событиями с единым API и пулингом для производительности. e.preventDefault() отменяет действие по умолчанию (перезагрузка формы), e.stopPropagation() останавливает всплытие.

      Controlled component — input, значение которого полностью контролируется React state. Для text input: value={text} + onChange={e => setText(e.target.value)}. Для checkbox: checked={done} + onChange, не value. Для select: value={priority} на <select>, не selected на <option>. Группа radio: один state, разные value у <input type="radio">.

      Разница readOnly и disabled: disabled элемент не участвует в tab-навигации и не отправляется с формой; readOnly виден и фокусируем, но не редактируется. defaultValue вместо value делает компонент uncontrolled — React не управляет значением после первого рендера. Для форм с валидацией и сбросом предпочитай controlled.

      +

      Мысленная модель controlled input — однонаправленный цикл: state → JSX (value) → DOM показывает значение → пользователь печатает → событие onChange → setState → React перерисовывает input с новым value. React в этой схеме — единственный источник правды, а DOM-элемент — лишь его «зеркало». Как только это закольцовано, становится понятно, зачем вообще нужен onChange: не только для валидации, а чтобы замкнуть цикл и не дать полю «зависнуть» со старым значением.

      +

      Эта модель критична для всего, что будет дальше: формы с валидацией (день 82), поиск с debounce (неделя 13), позже — библиотеки вроде React Hook Form, которые под капотом используют тот же паттерн, просто оптимизированный. Понимание controlled-цикла также объясняет, почему в React сложно «просто взять и вставить jQuery-плагин» — он мутирует DOM в обход React, и React в следующем рендере затирает изменения.

      +

      Конкретный пример: поле поиска <input value={query} onChange={e => setQuery(e.target.value)} /> — при каждом нажатии клавиши React перерисовывает input с тем же символом, который пользователь только что ввёл, поэтому визуально ничего не «дёргается», хотя фактически элемент каждый раз получает новый value из state.

      +

      Частая ошибка новичков — задать value только при определённом условии (например, value={isEditing ? text : undefined}), из-за чего React в консоли ругается на переключение input между controlled и uncontrolled в процессе жизни компонента. Правило: если хоть раз указал value, указывай его всегда, даже пустой строкой. Именно эта дисциплина понадобится при переписывании Todo App: чекбокс, textarea и select в одной форме должны быть либо все controlled, либо ни один — смешение ведёт к трудноуловимым багам с фокусом и потерянными нажатиями клавиш.

      Читать: - React — Responding to Events - React — Forms @@ -136,7 +144,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      Git

      
       cd learning-log/week-12
      @@ -158,14 +166,18 @@ 

      Ловушки


      День 80 (Ср): useEffect — побочные эффекты

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к React Todo Pro

      Теория

      useEffect синхронизирует React-компонент с внешними системами: DOM API, таймеры, подписки, fetch, localStorage. Сигнатура: useEffect(() => { /* effect */ return () => { /* cleanup */ }; }, [deps]). Пустой массив deps [] — effect выполнится один раз при mount (аналог componentDidMount). [dep] — при изменении dep. Без массива deps — при каждом рендере (почти всегда ошибка).

      Cleanup function вызывается перед повторным effect и при unmount: отписка от событий, очистка таймера, abort fetch. Без cleanup — утечки памяти и warnings. React Strict Mode в dev намеренно mount → unmount → mount, чтобы выявить missing cleanup.

      Не всё требует effect. You Might Not Need an Effect: вычисление derived state, обработка клика, валидация формы — это event handlers, не effects. Effect — для синхронизации с внешним миром, когда нет события-повода. Stale closure — классический баг: effect с [] использует устаревший props/state; добавь их в deps. useLayoutEffect выполняется синхронно после DOM-мутаций, до paint — для измерений layout (обзор).

      +

      Полезная мысленная модель, которую подчёркивает сама документация React: useEffect — это не аналог componentDidMount/Update/WillUnmount, а декларативное описание синхронизации. Ты не говоришь React «выполни это после рендера», а говоришь «эта внешняя система должна быть согласована с такими-то значениями»; React сам решает, когда пересинхронизировать — при монтировании, при изменении зависимости, при размонтировании (тогда вызывается cleanup, который «отменяет» предыдущую синхронизацию перед новой).

      +

      Эта модель станет ключевой на следующий день при работе с fetch (effect синхронизирует UI с состоянием сервера) и через неделю — при написании custom hooks, где вся эта логика инкапсулируется. Она же объясняет глубже, зачем нужен строгий список зависимостей: если effect читает props.city, а зависимостей нет, React не знает, что нужно пересинхронизироваться при смене города — эффект продолжает работать со старым значением из замыкания (тот самый stale closure).

      +

      Конкретный пример синхронизации: document.title должен отражать открытую задачу. Effect useEffect(() => { document.title = task.name }, [task.name]) — это не «побочный эффект ради эффекта», а честная синхронизация DOM API (заголовок вкладки) с состоянием React (task.name).

      +

      Частое заблуждение — думать, что зависимости управляют «когда запускать effect», как будто это таймер. На самом деле зависимости — это список всех значений извне, которые effect читает; если хоть одно из них не указано, ESLint exhaustive-deps справедливо ругается, потому что effect может работать с устаревшими данными. Ещё одна ошибка — забыть, что cleanup выполняется не только при unmount, но и перед каждым повторным запуском effect, из-за чего Pomodoro-таймер без правильной очистки заводит второй setInterval поверх первого при каждом ререндере, ускоряя обратный отсчёт вместо того, чтобы просто тикать раз в секунду — именно это стоит поймать в практике этого дня на примере таймера и синхронизации localStorage.

      Читать: - useEffect - You Might Not Need an Effect @@ -204,7 +216,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

      +

      Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

      Git

      
       cd learning-log/week-12
      @@ -226,14 +238,18 @@ 

      Ловушки


      День 81 (Чт): Fetch и паттерн loading/error/data

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к React Todo Pro

      Теория

      Загрузка данных в React-компоненте — классический сценарий для useEffect + fetch. Паттерн трёх (или четырёх) состояний: loadingsuccess / error / empty. Реализуй через отдельные useState или discriminated union: { status: 'loading' } | { status: 'error', error: string } | { status: 'success', data: T }. UI рендерит разную разметку в зависимости от status.

      В effect: fetch(url).then(res => { if (!res.ok) throw new Error(); return res.json() }).then(setData).catch(setError).finally(() => setLoading(false)). Fetch не reject на HTTP 404 — проверяй res.ok. Race condition: пользователь быстро переключает id, старый ответ приходит последним. Решение — AbortController в cleanup: const ctrl = new AbortController(); fetch(url, { signal: ctrl.signal }); return () => ctrl.abort().

      Не вызывай setState на размонтированном компоненте — abort или флаг let cancelled = false в cleanup. Custom hook useFetch<T>(url) инкапсулирует весь паттерн: loading, error, data, refetch. Skeleton UI вместо пустого экрана улучшает perceived performance.

      +

      Мысленная модель здесь — конечный автомат (state machine), а не набор независимых булевых флагов. Если завести отдельные isLoading, isError, data через три useState, ничто не мешает коду случайно оказаться в невозможном состоянии: isLoading = true и isError = true одновременно, хотя по смыслу это взаимоисключающие стадии одного запроса. Discriminated union ({ status: 'idle' | 'loading' | 'success' | 'error', ... }) на уровне типов делает невозможные комбинации невозможными — компилятор TypeScript просто не даст обратиться к data, если status !== 'success'.

      +

      Это ровно тот паттерн, который будет использоваться весь курс дальше: на неделе 14 при загрузке погоды, на неделях 21–22 при интеграции с собственным backend, и позже как база для понимания библиотек вроде React Query или SWR, которые решают тот же automaton плюс кэширование и повторные запросы.

      +

      Конкретный пример race condition: пользователь на PostDetail быстро кликает id=1, затем id=2. Запрос за id=1 может по сети завершиться позже, чем запрос за id=2 (например, из-за более тяжёлого ответа), и тогда экран покажет пост id=1, хотя выбран id=2. AbortController в cleanup effect решает это: при смене id предыдущий fetch отменяется до того, как его .then() успеет вызвать setData с устаревшими данными.

      +

      Частое заблуждение — считать, что достаточно проверить loading, чтобы «на всякий случай» не показывать старые данные; на самом деле без abort или флага cancelled возможен путь, когда компонент уже перешёл к новому запросу, а старый .then() всё равно сработает и молча перезапишет актуальные данные. Именно поэтому в критериях дня явно требуется AbortController в cleanup, а не просто спиннер поверх контента — это прямая защита от этой ошибки при реализации PostList, PostDetail и обобщающего useFetch.

      Читать: - MDN: Fetch API - MDN: AbortController @@ -272,7 +288,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

      +

      Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

      Git

      
       cd learning-log/week-12
      @@ -294,14 +310,18 @@ 

      Ловушки


      День 82 (Пт): Формы в React

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к React Todo Pro

      Теория

      Формы в React строятся на controlled components: каждое поле связано с state. Для формы из нескольких полей два подхода: отдельный useState на поле (проще для маленьких форм) или один объект const [form, setForm] = useState({ name: '', email: '' }) с обновлением setForm(f => ({ ...f, name: e.target.value })). Второй удобен для submit целиком и сброса.

      Валидация на клиенте: required, minLength, regex для email, кастомные правила (пароль ≥ 8 символов). UX-паттерн touched/dirty: показывай ошибки после blur или submit, не при первом символе — это меньше раздражает. useId() генерирует стабильный уникальный id для связки <label htmlFor={id}> и <input id={id}> — важно для accessibility.

      Сброс формы: верни state к начальным значениям. noValidate на <form> отключает браузерную валидацию, если реализуешь свою. Checkbox «согласен с условиями» — отдельный boolean state, блокирующий submit. React 19 Form Actions (обзор) упрощают submit через action prop, но controlled подход остаётся фундаментом.

      +

      Мысленная модель формы: единый объект состояния полей (form) плюс отдельный, вычисляемый на каждый рендер объект ошибок (errors), а не два независимых, синхронизируемых вручную state. Ошибки — производная функция от form и правил валидации: validate(form) вызывается при рендере или в обработчике submit/blur, а не хранится как отдельный useState, который легко забыть обновить и получить рассинхрон между полем и текстом ошибки под ним.

      +

      Это станет фундаментом для форм логина на день 89 этой же недели (React Router + Context), а позже — для форм, отправляющих данные на собственный backend (недели 21+), где к клиентской валидации добавится обработка ошибок сервера (409 Conflict на занятый email и подобное) поверх той же структуры state.

      +

      Конкретный пример: поле «Подтвердите пароль» валидируется не изолированно, а в сравнении с полем «Пароль» — errors.confirmPassword = form.password !== form.confirmPassword ? 'Пароли не совпадают' : null. Это наглядно показывает, что ошибка — производная от всей формы, а не свойство одного поля.

      +

      Частое заблуждение — показывать ошибку сразу при первом введённом символе: пользователь ещё не закончил печатать email, а поле уже красное. UX-паттерн touched/dirty (ошибка показывается после blur или после первой попытки submit) снижает раздражение, но требует дисциплины: touched — тоже часть state формы, обновляемая в onBlur. Другая типичная ошибка — хранить isFormValid отдельным state вместо вычисления Object.keys(errors).length === 0 при каждом рендере; при отдельном state легко забыть его обновить после изменения одного из полей, и кнопка submit останется disabled даже у корректно заполненной формы. Именно такую логику нужно продумать при реализации формы регистрации: имя, email, пароль с подтверждением и чекбокс согласия должны валидироваться согласованно, без рассинхрона между полем, ошибкой и состоянием кнопки.

      Читать: - React — Forms - React — input @@ -362,14 +382,18 @@

      Ловушки


      День 83 (Сб): Подъём state (lifting state up)

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к React Todo Pro

      Теория

      Lifting state up (подъём состояния) решает задачу, когда два или более компонента должны отображать или изменять одни данные. State перемещается к ближайшему общему родителю. Родитель хранит данные и передаёт вниз через props; дети сообщают об изменениях через callback props (onSearchChange, onSortChange). Siblings никогда не общаются напрямую — только через родителя.

      Derived state — значения, вычисляемые из props или state при рендере: const filtered = items.filter(i => i.title.includes(query)). Не дублируй их в отдельном useState — иначе рассинхрон при обновлении источника. Prop drilling на 1–2 уровня — нормально; при глубокой вложенности (неделя 13) поможет Context.

      Container/Presentational split: «умный» компонент управляет state и логикой, «глупый» — только рендерит по props. useMemo (preview) кэширует результат дорогой фильтрации: useMemo(() => items.filter(...), [items, query]) — пересчёт только при изменении deps. Для 10 элементов не нужен; для 1000+ — заметная оптимизация.

      +

      Мысленная модель для lifting state up формулируется просто: «state должен жить настолько низко, насколько возможно, и настолько высоко, насколько необходимо». Это значит — не поднимай вообще всё в корень приложения «на всякий случай»: если состояние нужно только одному компоненту (например, открыт ли dropdown), оно остаётся локальным; поднимается только то, что реально требуется нескольким потребителям одновременно.

      +

      Этот баланс станет критичным на следующей неделе, когда drilling через 4–5 уровней станет неудобным и появится соблазн засунуть вообще всё в Context. Понимание сегодняшнего правила помогает не наступить на грабли «Context для всего»: то, что нужно двум соседним компонентам на одном уровне, поднимается к родителю (как сегодня), а Context нужен только для данных, нужных по-настоящему широко и на разной глубине дерева (тема, авторизация).

      +

      Конкретный пример: SearchBar не может держать searchQuery у себя, а ItemList — фильтровать по нему, если они не знают друг о друге. Оба — дети одного родителя FilterableList, значит, searchQuery поднимается именно туда: родитель хранит state, передаёт value и onChange в SearchBar, а отфильтрованный список — в ItemList.

      +

      Частая ошибка — воспринять «lifting state up» как сигнал переносить в родителя вообще все данные компонента, включая чисто визуальные вещи вроде «наведена ли мышь на элемент» или «раскрыт ли аккордеон» — это только раздувает родителя и провоцирует лишние ререндеры всего поддерева при каждом мелком UI-взаимодействии. Правило простое: поднимай ровно то состояние, которое читают или меняют минимум два разных компонента; всё остальное остаётся локальным. Именно на этом принципе строится рефакторинг Todo App в практике дня: filter и searchQuery поднимаются в общий родитель, а, например, состояние «редактируется ли конкретная задача прямо сейчас» может вполне остаться внутри TodoItem.

      Читать: - Sharing State Between Components - react.dev: Extracting State Logic into a Reducer — preview @@ -408,7 +432,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

      +

      Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

      Git

      
       cd learning-log/week-12
      @@ -430,14 +454,18 @@ 

      Ловушки


      День 84 (Вс): Ревью и углубление

      -

      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к React Todo Pro

      Теория

      Ревью недели — время закрепить правила hooks и подготовиться к React Todo Pro. Правила hooks: вызывай только на верхнем уровне (не в if/for) и только в React-функциях (компонентах или custom hooks). Нарушение ломает порядок hooks между рендерами. Custom hook — функция useTodos(), внутри которой useState + handlers; компонент остаётся тонким, логика переиспользуема.

      React DevTools показывают дерево компонентов, props и state в реальном времени — незаменимый инструмент отладки. ESLint react-hooks/exhaustive-deps предупреждает о missing dependencies в useEffect — не отключай правило без веской причины и комментария. Strict Mode двойной mount — норма в dev, не баг.

      Чеклист code review: state обновляется иммутабельно, effects имеют cleanup, inputs controlled, deps корректны, нет setState на unmounted компоненте. Конспект «useState vs useEffect»: state — для данных UI, effect — для синхронизации с внешним миром. Подготовка к Todo Pro: приоритеты, дедлайны, Quotable API — всё на базе изученных паттернов.

      +

      Мысленная модель, объясняющая Rules of Hooks: React хранит хуки одного компонента как позиционный список — при каждом рендере он ожидает вызовы useState, useEffect и других хуков строго в одном и том же порядке, чтобы сопоставить i-й вызов с i-й ячейкой памяти. Хук не «знает» своё имя переменной, только позицию вызова. Если между рендерами хук иногда вызывается, а иногда пропускается (например, из-за if перед useState), позиции всех последующих хуков смещаются, и React начинает путать состояние одного хука с другим.

      +

      Это понимание становится обязательным на следующей неделе при написании собственных custom hooks: любая условная логика внутри useLocalStorage или useFetch должна быть внутри хука, а не вокруг вызова самого хука. Ошибка на этом уровне не бросает явное исключение сразу — она проявляется как труднообъяснимый баг «состояние перепуталось» через несколько рендеров, что делает её особенно коварной в более крупных проектах.

      +

      Конкретный пример нарушения: if (user) { const [notifications] = useState([]); } — если user появляется не сразу, а после начального рендера, хук, который раньше был третьим по счёту, эту логику меняет, и React ломает сопоставление предыдущих состояний с новыми вызовами.

      +

      Частое заблуждение — воспринимать хуки как «обычные функции», которые можно оборачивать в любые конструкции языка, как обычный useCallback-помощник. На самом деле особый рантайм React делает их зависимыми от порядка вызова, а не от имени — отсюда и линтер react-hooks/rules-of-hooks, который стоит воспринимать не как формальность, а как страховку от невидимых багов. В практике дня это напрямую связано с вынесением логики Todo в useTodos: рефакторинг должен сохранить безусловный порядок вызовов хуков, а Tic-Tac-Toe из официального туториала — хорошая тренировка на управление историей состояния через массив снимков, ту же модель, что используется в Undo/Redo многих реальных приложений.

      Читать: - React DevTools - Rules of Hooks @@ -476,7 +504,7 @@

      Практика (лайт / MVP)

      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

      Если застрял

      -

      Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

      +

      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

      Git

      
       cd learning-log/week-12
      diff --git a/docs/w/13.html b/docs/w/13.html
      index 7363779..4d96998 100644
      --- a/docs/w/13.html
      +++ b/docs/w/13.html
      @@ -22,14 +22,18 @@
       
       

      День 85 (Пн): React Router — основы

      -

      Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
      -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
      +

      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
      Связь с проектом: шаг к Portfolio SPA

      Теория

      Одностраничное приложение (SPA) живёт в одной HTML-странице, но пользователь ожидает поведение «настоящего сайта»: разные URL, кнопка «Назад» в браузере, закладки на конкретные экраны. React Router решает эту задачу на клиенте: при смене маршрута он размонтирует один набор компонентов и смонтирует другой, не перезагружая документ целиком.

      Три кита базовой настройки — BrowserRouter, Routes и Route. Router подключает приложение к History API браузера (pushState под капотом); Routes выбирает единственный подходящий маршрут; Route связывает путь с компонентом. Для навигации внутри SPA используй Link или NavLink: они меняют URL без полной перезагрузки, в отличие от обычного <a href>, который сбрасывает состояние приложения.

      Layout с <Outlet /> — стандартный паттерн общей оболочки: шапка и меню остаются на месте, а содержимое страницы подставляется в outlet. Catch-all маршрут path="*" обязателен для 404. При деплое в subdirectory (GitHub Pages) понадобится basename; сервер должен отдавать index.html на все пути, иначе прямой заход по URL /about вернёт 404 от nginx, а не твой React-компонент.

      +

      Мысленная модель React Router: URL — это ещё один источник состояния приложения, только он живёт не в React, а в браузере (History API), и Router — это просто мост, который синхронизирует адресную строку с деревом React-компонентов. Смена маршрута — это не HTTP-запрос за новой страницей, а вызов pushState, который меняет URL без перезагрузки, после чего Routes перечитывает текущий путь и решает, какое поддерево компонентов сейчас должно быть смонтировано.

      +

      Эта модель — фундамент всего, что будет дальше на неделе: вложенные маршруты (день 86) — это просто вложенные решения «какое поддерево показать»; protected routes (день 89) — это условный рендер <Navigate> вместо целевого компонента; а на деплое (день 91) станет ясно, что клиентский роутинг работает только пока JS-бандл загружен в браузере — прямой заход по URL требует отдельной настройки сервера.

      +

      Конкретный пример путаницы клиент/сервер: пользователь кликает NavLink на /about — React Router перехватывает клик, меняет URL через pushState и рендерит About без единого сетевого запроса. Но если тот же пользователь наберёт /about в адресной строке и нажмёт Enter, браузер отправит настоящий HTTP-запрос на сервер, и если сервер (nginx, statically-hosted файлы) не настроен отдавать index.html на любой путь, он ответит честным 404 Not Found — не потому что React сломался, а потому что запрос вообще не дошёл до React.

      +

      Частое заблуждение новичков — думать, что React Router «делает запросы» за страницы, как многостраничный сайт, и что 404 при обновлении страницы — это баг библиотеки, а не следствие неправильной настройки сервера или отсутствия basename при деплое в поддиректорию. Именно поэтому в практике дня явно указан пункт «прямой переход по URL /about работает» — это проверка не только кода, но и понимания разницы между dev server (который из коробки настроен на SPA fallback) и продакшен-хостингом, который нужно настраивать отдельно.

      Читать:

      • React Router — Tutorial
      • @@ -93,14 +97,18 @@

        Ловушки


        День 86 (Вт): Динамические маршруты и nested routes

        -

        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
        -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
        +

        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
        +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
        Связь с проектом: шаг к Portfolio SPA

        Теория

        Статический маршрут /about покрывает фиксированную страницу, но реальные приложения оперируют сущностями с идентификаторами: посты, проекты, профили. Динамический сегмент /blog/:slug превращает часть URL в параметр, который компонент читает через useParams. Помни: все параметры приходят строками — для чисел нужны Number() или явная валидация.

        Вложенные маршруты (nested routes) строят иерархию UI: общий layout для раздела /blog и дочерние страницы списка и детали. Родительский Route рендерит layout с <Outlet />; без outlet дочерние страницы просто не появятся — классическая ловушка. Index route задаёт страницу по умолчанию, когда пользователь открывает родительский путь без суффикса.

        Query string (?sort=date&tab=comments) описывает фильтры и вкладки, не меняя структуру пути. useSearchParams даёт к ним доступ в React-стиле. useLocation полезен для breadcrumbs и для передачи временного state при navigate('/path', { state: { from: 'list' } }). В React Router 6.4+ useMatches помогает строить цепочку навигации из дерева маршрутов.

        +

        Мысленная модель вложенных маршрутов — русская матрёшка: родительский Route рендерит свой layout, а <Outlet /> — это буквально дыра в этом layout, куда React Router подставляет компонент дочернего маршрута. Если у /blog есть общий сайдбар с категориями, а /blog/:slug показывает конкретный пост, то сайдбар рендерится один раз на уровне родителя и не размонтируется при переходе между постами — меняется только содержимое outlet.

        +

        Эта модель прямо переносится на Dashboard недели 14: общий Layout с навигацией остаётся смонтированным, пока пользователь переключается между /tasks, /weather и /settings — размонтируется и монтируется заново только содержимое конкретной страницы. То же самое почти в любом реальном приложении с админкой: общая рамка интерфейса не должна перерисовываться при переходе между разделами.

        +

        Конкретный пример: URL /blog/react-hooks-guideslug в useParams() придёт строкой "react-hooks-guide", и если это на самом деле числовой id поста (/blog/42), useParams().id всё равно будет строкой "42", а не числом 42. Сравнение id === 42 без Number(id) всегда будет false, хотя внешне всё выглядит правильно — классическая ловушка, о которой явно предупреждают «Ловушки» этого дня.

        +

        Частое заблуждение — полагать, что если родительский Route определён, дочерние страницы появятся «автоматически». Без явного <Outlet /> в JSX родительского компонента React Router прекрасно вычисляет, какой маршрут совпал, но рендерить его содержимое ему буквально некуда — сайдбар покажется, а сам пост — нет, и разработчик потратит время на поиск несуществующего бага в дочернем компоненте, хотя проблема в layout на уровень выше. В практике дня именно это нужно проверить в первую очередь при вёрстке /blog с сайдбаром категорий и вложенной страницей поста.

        Читать:

        • Nested Routes
        • @@ -141,7 +149,7 @@

          Практика (лайт / MVP)

          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

          Если застрял

          -

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

          +

          Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

          Git

          
           cd learning-log/week-13
          @@ -163,14 +171,18 @@ 

          Ловушки


          День 87 (Ср): Custom Hooks — переиспользование логики

          -

          Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
          -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
          +

          Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
          +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
          Связь с проектом: шаг к Portfolio SPA

          Теория

          Custom hook — обычная функция с префиксом use, внутри которой вызываются другие хуки. Она не добавляет новых возможностей React, а выносит повторяющуюся логику из компонентов: синхронизацию с localStorage, загрузку данных, debounce ввода. Компонент остаётся про UI, хук — про поведение.

          Типичный useLocalStorage(key, initial) комбинирует useState и useEffect: при изменении state значение пишется в storage, при монтировании — читается обратно. Оборачивай JSON.parse в try/catch — битые данные не должны ронять приложение. useFetch(url) инкапсулирует три состояния (loading, error, data) и избавляет каждую страницу от копипасты useEffect.

          useDebounce(value, delay) откладывает обновление: пока пользователь печатает в поиске, тяжёлая фильтрация не запускается на каждый символ. Правила хуков действуют и внутри custom hook — нельзя вызывать хуки условно. Возвращай объект { data, loading } или tuple, но придерживайся одного стиля в проекте.

          +

          Мысленная модель custom hook: это не мини-компонент, а способ переиспользовать «поведение» без переиспользования UI. Хорошая аналогия — рецепт: useLocalStorage(key, initial) — это рецепт «состояние + синхронизация с storage», который можно применить к любым данным (тема, задачи, черновик формы), просто передав другой ключ. Важно, что каждый вызов хука создаёт полностью независимый экземпляр состояния: два компонента, вызвавшие useLocalStorage('theme', 'light') и useLocalStorage('draft', ''), не делят между собой ничего, кроме одинаковой логики внутри.

          +

          Это прямо готовит к неделе 14, где почти всё приложение строится вокруг custom hooks: useTasks инкапсулирует CRUD и persist, а Dashboard и страница /tasks используют один и тот же хук вместо копирования логики в двух местах. Такой подход — стандартная практика в реальных React-кодовых базах, а не учебное упражнение.

          +

          Конкретный пример переиспользования: useLocalStorage из этого дня одинаково подходит и для theme (день 88, Context), и для tasks (неделя 14) — меняется только ключ и тип данных, логика синхронизации с localStorage и обработка битого JSON через try/catch не дублируется.

          +

          Частое заблуждение — путать custom hook с компонентом из-за префикса use и думать, что он должен возвращать JSX. На самом деле custom hook — это обычная функция, которая возвращает данные и функции (объект или массив), а не разметку; она не рендерит ничего сама по себе, только управляет состоянием и эффектами, которые уже само использующий её компонент решает, как отобразить. Ещё одна ошибка — забыть, что правила хуков (порядок вызова, только на верхнем уровне) действуют и внутри custom hook: если внутри useDebounce условно вызвать useEffect, это сломает тот же механизм позиционного сопоставления, что и в обычном компоненте — именно поэтому «Ловушки» дня отдельно упоминают запрет условных вызовов хуков.

          Читать:

          • Custom Hooks
          • @@ -211,7 +223,7 @@

            Практика (лайт / MVP)

            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

            Если застрял

            -

            Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

            +

            Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

            Git

            
             cd learning-log/week-13
            @@ -233,14 +245,18 @@ 

            Ловушки


            День 88 (Чт): Context API — глобальное состояние

            -

            Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
            -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
            +

            Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
            +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
            Связь с проектом: шаг к Portfolio SPA

            Теория

            Prop drilling — передача props через пять уровней дерева — быстро превращает код в лабиринт. Context API даёт альтернативу: Provider в корне публикует значение, любой потомок читает его через useContext без промежуточных компонентов. Классические кандидаты: тема оформления, язык интерфейса, данные текущего пользователя.

            createContext(defaultValue) создаёт контекст; default нужен для подсказок в dev и как fallback, если забыли Provider. Разделяй контексты по доменам: ThemeContext отдельно от UserContext, иначе смена темы перерисует всё дерево, включая компоненты, которым нужен только user. Оборачивай value Provider в useMemo, если передаёшь объект или функции.

            Context не заменяет локальный state и не является полноценным store. Документация React предупреждает: не тащи в Context часто меняющиеся данные. Для сложного глобального state комбинация Context + useReducer — разумный следующий шаг, но для учебного проекта двух отдельных контекстов (theme + user) достаточно.

            +

            Мысленная модель Context — это broadcast-канал для целого поддерева: Provider публикует значение один раз в корне, и любой компонент внутри, независимо от глубины вложенности, может подписаться на него через useContext, как будто настроившись на нужную «радиоволну», без необходимости, чтобы каждый промежуточный компонент знал об этом значении и передавал его дальше через props.

            +

            Эта модель прямо используется в дне 89 этой же недели для AuthContext (сессия пользователя видна на любом маршруте без drilling через каждый layout) и станет ещё важнее на неделе 14, где ThemeContext и UserContext должны быть видны одновременно и в Dashboard, и в Settings, и в шапке навигации — трём совершенно разным веткам дерева компонентов.

            +

            Конкретный пример: переключатель темы на странице /settings меняет theme в ThemeContext; хедер на / и карточки на /tasks, ни один из которых не связан прямым родительско-дочерним отношением с формой настроек, мгновенно перерисовываются с новым классом dark — потому что все они подписаны на один и тот же Provider, а не потому что кто-то явно передал им новое значение через props.

            +

            Частое заблуждение — воспринимать Context как замену полноценного стейт-менеджера и пытаться засунуть туда вообще весь state приложения одним большим объектом. Проблема не только концептуальная, но и практическая: при таком подходе изменение любого поля (даже никак не связанного с большинством потребителей) вызывает ререндер всех компонентов, подписанных на этот Context, потому что React сравнивает ссылку на весь объект value, а не отдельные поля внутри него. Именно поэтому день явно требует разделять ThemeContext и UserContext — смена имени пользователя не должна лишний раз перерисовывать компоненты, которым нужна только тема. Это ровно та дисциплина, которую нужно соблюсти в практике: два независимых провайдера, а не один «God Context» на всё приложение.

            Читать:

            • createContext
            • @@ -281,7 +297,7 @@

              Практика (лайт / MVP)

              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

              Если застрял

              -

              Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

              +

              Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

              Git

              
               cd learning-log/week-13
              @@ -303,14 +319,18 @@ 

              Ловушки


              День 89 (Пт): Комбинация Router + Context + Hooks

              -

              Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
              -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
              +

              Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
              +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
              Связь с проектом: шаг к Portfolio SPA

              Теория

              На этой неделе складываются три слоя: Router отвечает за URL, Context — за глобальное состояние (auth, theme), custom hooks — за переиспользуемую логику. Protected route — тонкая обёртка: если в AuthContext нет пользователя, рендерится <Navigate to="/login" replace />, иначе — дочерняя страница.

              Mock-авторизация без реального API — нормальная ступень обучения: сохраняй объект user в localStorage, восстанавливай при старте. Без persist пользователь «разлогинится» после F5. Logout должен атомарно очистить Context, storage и перенаправить на публичную страницу через useNavigate или декларативный <Navigate>.

              Разделяй ответственность: форма логина — controlled inputs; проверка доступа — в ProtectedRoute; данные сессии — в Context. location.state позволяет передать, откуда пришёл пользователь, чтобы после login вернуть его на исходную страницу, а не всегда на /dashboard.

              +

              Мысленная модель сегодняшнего дня — три независимых слоя, которые взаимодействуют, но не смешиваются: Router отвечает на вопрос «где мы» (URL → компонент), Context — «что мы знаем» (авторизован ли пользователь, какая тема), custom hooks — «как это переиспользуется» (логика внутри useLocalStorage, применённая теперь к сессии). ProtectedRoute — это gatekeeper на стыке первых двух слоёв: он не хранит состояние сам, а лишь читает AuthContext и решает, пропустить дальше к маршруту или подменить его на <Navigate to="/login" />.

              +

              Этот паттерн — не учебная условность, а форма, в которой строятся почти все продакшен-приложения: на неделях 20+ появится настоящий backend с JWT-токенами, но структура останется той же — AuthContext будет хранить не мок-пользователя, а результат проверки токена, а ProtectedRoute не изменится вообще. Понимание сегодняшней архитектуры экономит недели путаницы позже, когда вместо мока появится реальный API.

              +

              Конкретный пример UX-цепочки: неавторизованный пользователь пытается открыть /dashboard, ProtectedRoute перенаправляет на /login, попутно сохраняя исходный путь через location.state = { from: '/dashboard' }; после успешного (мок) логина navigate(state?.from ?? '/dashboard', { replace: true }) возвращает его именно туда, куда он изначально шёл, а не на дефолтную страницу — мелкая деталь, которая сильно улучшает ощущение от приложения.

              +

              Важная оговорка, которую стоит проговорить явно, чтобы не сформировать ложное чувство защищённости: client-side ProtectedRoute — это UX-фильтр, а не механизм безопасности. Весь JS-код, включая проверку if (!user), выполняется в браузере пользователя и может быть обойдён (просто отредактирован в DevTools) кем угодно с базовыми навыками. Реальная защита данных всегда происходит на сервере, который должен сам проверять права на каждый запрос — client-side роутинг лишь скрывает UI, но никогда не заменяет серверную авторизацию. Это прямо связано с пунктом «Ловушки»: сегодняшний ProtectedRoute проверяет только наличие объекта user, а не валидность токена — эта тема вернётся на неделе 20 уже с настоящим backend.

              Читать:

              • React Router — Tutorial (auth patterns)
              • @@ -373,14 +393,18 @@

                Ловушки


                День 90 (Сб): Оптимизация и структура проекта

                -

                Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                +

                Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                Связь с проектом: шаг к Portfolio SPA

                Теория

                К концу недели проект обрастает папками: pages/, components/, hooks/, contexts/, utils/. Предсказуемая структура важнее идеальной: новый разработчик (или ты через месяц) должен за минуту найти, где живут маршруты и где — хуки. ARCHITECTURE.md фиксирует решения, а не дублирует README с командами запуска.

                Оптимизация в React начинается с измерения, а не с useMemo на каждой функции. Profiler в DevTools показывает лишние ререндеры. React.lazy + Suspense разбивают bundle: тяжёлая страница /admin загружается только при переходе. useMemo оправдан для дорогих вычислений; useCallback — когда передаёшь колбэк в React.memo-компонент.

                Barrel exports (index.ts) ускоряют импорты, но могут ухудшить tree-shaking — используй осознанно. useCallback без memoized child бесполезен. Преждевременная мемоизация усложняет код без выигрыша: сначала работающее приложение, потом профилирование, потом точечные правки.

                +

                Мысленная модель оптимизации в React: сначала измерить, потом чинить, а не наоборот. Profiler в DevTools отвечает на вопрос «какой компонент действительно долго рендерится и почему», превращая интуитивные догадки в конкретные цифры (миллисекунды на конкретный commit). Без этого шага легко потратить время на мемоизацию компонента, который и так рендерится за доли миллисекунды, пропустив реальную проблему в другом месте дерева.

                +

                Это умение станет практически необходимым на неделе 14: Dashboard одновременно рендерит статистику, список задач и виджет погоды — без структуры и точечной оптимизации лишние ререндеры будут накапливаться незаметно, а профилирование покажет, где именно. Тот же навык прямо пригодится на реальной работе и часто спрашивается на технических собеседованиях как «как бы ты нашёл причину лагов в React-приложении».

                +

                Конкретный пример пользы lazy loading: страница /admin нужна редкому проценту пользователей, но её код (таблицы, формы, графики) может весить сотни килобайт. React.lazy(() => import('./pages/Admin')) в паре с <Suspense> гарантирует, что этот код не попадёт в основной bundle и не замедлит первую загрузку для обычного посетителя, который никогда не откроет /admin.

                +

                Частое заблуждение — воспринимать useMemo и useCallback как «бесплатную» оптимизацию, которую можно расставлять по коду на автомате. На самом деле у мемоизации есть своя цена: React должен хранить предыдущие зависимости и сравнивать их на каждом рендере, и если сравниваемое значение вычисляется быстрее, чем сам массив зависимостей проверяется, мемоизация не ускоряет код, а замедляет и усложняет его без всякой выгоды. Именно поэтому «Ловушки» дня прямо называют преждевременную оптимизацию проблемой — практика дня требует сначала реорганизовать структуру папок и задокументировать архитектуру, и только потом точечно применять useMemo там, где Profiler реально показал узкое место (например, фильтрация 1000+ элементов), а не «на всякий случай» по всему коду.

                Читать:

                • useMemo
                • @@ -422,7 +446,7 @@

                  Практика (лайт / MVP)

                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                  Если застрял

                  -

                  Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                  +

                  Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                  Git

                  
                   cd learning-log/week-13
                  @@ -444,14 +468,18 @@ 

                  Ловушки


                  День 91 (Вс): Ревью паттернов React

                  -

                  Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                  -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                  +

                  Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                  +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                  Связь с проектом: шаг к Portfolio SPA

                  Теория

                  За семь дней ты собрал многостраничное SPA с роутингом, глобальным state и переиспользуемыми хуками. Полезно явно сравнить инструменты: локальный state для UI формы, lifting state когда нужно двум соседям, custom hook для логики, Context для редких глобальных данных, внешний store (Zustand/Redux) — когда Context разрастается.

                  Error Boundary ловит ошибки рендеринга в дочерних компонентах и показывает fallback вместо белого экрана. Оберни <Routes> или отдельные страницы, чтобы сбой на /blog/:slug не убивал всё приложение. Boundary не ловит ошибки в event handlers и async-коде — только синхронный render.

                  Перед деплоем проверь client-side routing: хостинг должен отдавать index.html на все пути. Portfolio SPA — витрина навыков недели: осмысленные коммиты за 7 дней, preview URL, README с картой маршрутов. Скелет Dashboard на неделю 14 логично начать с тех же паттернов Layout + Context + hooks.

                  +

                  Мысленная модель для выбора инструмента state — это шкала по двум осям: сколько компонентов читают/меняют значение и как часто оно меняется. Локальный useState — для UI одного компонента (открыт ли dropdown). Lifting state up — когда двум-трём соседям на одном уровне нужно одно значение (неделя 12, день 83). Context — когда значение нужно широко по дереву, но меняется редко (тема, сессия). Внешний store (Zustand, Redux, Jotai) — когда часто меняющихся глобальных данных становится много и Context начинает вызывать заметные лишние ререндеры. Эта шкала — не догма, а рабочий чеклист, который стоит прогонять в голове при старте каждой новой фичи.

                  +

                  Именно это умение станет решающим на неделе 14 при проектировании Dashboard (задачи — в custom hook или Context? тема — в Context, а фильтр списка — локальный useState?), а затем и в любом будущем проекте, включая приложения с backend, где к этой шкале добавится ещё один вопрос — что хранить на клиенте, а что запрашивать заново с сервера.

                  +

                  Конкретный пример выбора: поле поиска, фильтрующее список внутри одной страницы, — это локальный state или, максимум, lifting state между двумя соседними компонентами; заворачивать его в Context было бы избыточно и создало бы недокументированную глобальную связь там, где хватило бы пропса.

                  +

                  Частое заблуждение — считать, что «чем более глобально хранится состояние, тем безопаснее и удобнее», и по умолчанию тянуть данные в Context «на всякий случай», даже если ими пользуется один компонент. Другое похожее заблуждение — думать, что Error Boundary ловит вообще любые ошибки; на деле она перехватывает только синхронные ошибки рендеринга дочерних компонентов и не ловит исключения в обработчиках событий или внутри async кода (там нужен обычный try/catch). Оба заблуждения важно развеять перед финализацией Portfolio SPA: Error Boundary в практике дня оборачивает именно <Routes>, чтобы сбой рендера одной страницы (например, из-за некорректных данных :slug) не обрушивал всё приложение целиком, а не как универсальная страховка от любых ошибок.

                  Читать:

                  • React FAQ
                  • @@ -491,7 +519,7 @@

                    Практика (лайт / MVP)

                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                    Если застрял

                    -

                    Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                    +

                    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                    Git

                    
                     cd learning-log/week-13
                    diff --git a/docs/w/14.html b/docs/w/14.html
                    index 190dc7d..7dd6b7f 100644
                    --- a/docs/w/14.html
                    +++ b/docs/w/14.html
                    @@ -22,14 +22,18 @@
                     
                     

                    День 92 (Пн): Архитектура и скелет проекта

                    -

                    Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                    -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                    +

                    Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                    +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                    Связь с проектом: шаг к React Dashboard

                    Теория

                    Frontend capstone начинается с архитектуры, а не с кода. Прежде чем писать компоненты, зафиксируй страницы (/, /tasks, /weather, /settings), источники данных (localStorage, Context, внешний API) и границы ответственности модулей. Хороший скелет экономит дни рефакторинга на середине недели.

                    Vite отделяет переменные окружения по префиксу: только VITE_* попадают в клиентский bundle. API-ключи OpenWeather никогда не хардкодь — import.meta.env.VITE_WEATHER_API_KEY и .env.example без реальных значений. Файл .env в .gitignore, иначе ключ утечёт на GitHub.

                    Структура папок: pages/ для маршрутов, components/ui/ для переиспользуемых кнопок и карточек, hooks/ и contexts/ для логики, services/ для HTTP. Mobile-first CSS с CSS-переменными для темы закладывает адаптив с первого дня. Отдельная папка learning-log/week-14/ с чистой git-историей — привычка, которая пригодится в capstone.

                    +

                    Мысленная модель дня: архитектура — это чертёж здания, а код — это стройка. Ты же не начинаешь строить дом, пока не решил, сколько этажей, где несущие стены и куда идут трубы. Точно так же час, потраченный на ARCHITECTURE.md с описанием страниц, источников данных и границ модулей, экономит дни переписывания кода в середине недели, когда выяснится, что задачи нужны сразу и на Dashboard, и на /tasks, а состояние для них рассовано по разным местам.

                    +

                    Это особенно критично именно для capstone-проекта такого масштаба: впервые за курс собирается приложение с четырьмя полноценными страницами, внешним API и persist-слоем одновременно. Без предварительного плана велик риск «big ball of mud» — кода, который работает, но настолько запутан, что даже автор через три дня не может быстро найти, где лежит логика фильтрации задач.

                    +

                    Конкретный пример решения, которое стоит принять именно сегодня, а не на день 94: задачи должны читаться через один useTasks hook (или Context поверх него), которым пользуются и Dashboard (для статистики), и страница /tasks (для CRUD) — если это не зафиксировать заранее, велик соблазн написать useLocalStorage('tasks') в двух местах независимо, а затем удивляться, почему изменения не синхронизируются.

                    +

                    Частое заблуждение — думать, что .env файл автоматически безопасен просто потому, что не закоммичен явно руками; на самом деле любой файл, случайно не попавший в .gitignore до первого коммита, останется в истории Git навсегда, даже если потом его удалить — поэтому .gitignore с .env нужно создать до, а не после первого git add .. Также важно понимать: VITE_* переменные всё равно оказываются в финальном JS-бандле, видимом любому пользователю в DevTools — это защита от случайного коммита секрета в репозиторий, а не от раскрытия ключа в браузере. Именно поэтому OpenWeather API-ключ, который появится через несколько дней, — не секрет высокого риска, но привычку хранить его через .env.example стоит выработать уже сегодня, при закладке скелета проекта.

                    Читать:

                    • Vite — Env Variables
                    • @@ -92,14 +96,18 @@

                      Ловушки


                      День 93 (Вт): Dashboard — статистика и карточки

                      -

                      Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                      +

                      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                      Связь с проектом: шаг к React Dashboard

                      Теория

                      Главная страница Dashboard — витрина приложения: несколько независимых виджетов в единой сетке. Композиция через мелкие компоненты (StatCard, Grid) проще в поддержке, чем один монолитный Dashboard.tsx. Каждая карточка получает данные через props или hooks и не знает о соседях.

                      CSS Grid с repeat(auto-fit, minmax(240px, 1fr)) даёт адаптив без десятка media queries: на мобиле одна колонка, на desktop — четыре. Статистика задач — derived state: вычисляй total и done из массива tasks, не дублируй в отдельном useState, иначе рассинхрон неизбежен.

                      useMemo здесь оправдан, если фильтрация или агрегация затратна. Skeleton-карточки при загрузке предотвращают layout shift (CLS). Для иконок предпочитай inline SVG или библиотеку вроде lucide-react; у декоративных иконок добавляй aria-hidden, у смысловых — aria-label.

                      +

                      Мысленная модель Dashboard — это сетка независимых виджетов, каждый из которых «глухой» к соседям: StatCard знает только свои title, value, icon, но ничего не знает о том, что рядом ещё три такие же карточки и откуда вообще берутся данные. Композиция из простых, переиспользуемых кусочков — надёжнее, чем один компонент Dashboard.tsx на 300 строк, где логика статистики, погоды и приветствия перемешаны в одном JSX-дереве.

                      +

                      Этот подход — не специфика учебного проекта, а стандарт для любых аналитических интерфейсов и админ-панелей в индустрии: StatCard, ChartWidget, ActivityFeed — везде один и тот же принцип «глупый переиспользуемый компонент + умный контейнер, который считает данные».

                      +

                      Конкретный пример derived state: карточка «Задачи: 5 из 12 выполнено» не должна хранить total и done в отдельном useState, который нужно вручную обновлять при каждом добавлении/удалении/переключении задачи. Правильно — вычислять const done = tasks.filter(t => t.done).length прямо при рендере: тогда карточка гарантированно не может «отстать» от реальных данных, что бы ни произошло со списком задач.

                      +

                      Частое заблуждение — «закешировать» подобную статистику в отдельном state ради мнимой оптимизации: якобы пересчитывать filter на каждый рендер дорого. На практике для списков из десятков-сотен задач эта операция занимает доли миллисекунды, а риск рассинхрона (пользователь отметил задачу выполненной, а карточка показывает старое число, потому что забыли обновить отдельный state) — это реальный баг, который случится почти гарантированно. Правило простое: сначала derived state при рендере, и только если Profiler покажет реальную проблему производительности — useMemo вокруг вычисления, но не преждевременно. Это прямо связано с критерием дня «карточки обновляются при изменении tasks» — самый надёжный способ гарантировать это свойство — не хранить копию данных вообще.

                      Читать:

                      • MDN — CSS Grid
                      • @@ -140,7 +148,7 @@

                        Практика (лайт / MVP)

                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                        Если застрял

                        -

                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                        +

                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                        Git

                        
                         cd learning-log/week-14
                        @@ -162,14 +170,18 @@ 

                        Ловушки


                        День 94 (Ср): Tasks — CRUD и фильтрация

                        -

                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                        -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                        +

                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                        +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                        Связь с проектом: шаг к React Dashboard

                        Теория

                        Страница Tasks — сердце Dashboard: здесь проверяется, насколько чисто организован state. Custom hook useTasks становится единственным источником правды: и Dashboard, и /tasks читают одни данные через один hook (или Context-обёртку над ним). Дублирование логики в двух страницах — прямой путь к багам.

                        CRUD в React всегда иммутабелен: setTasks(prev => [...prev, newTask]), toggle через map, delete через filter. Фильтры и сортировка — derived state от tasks + filter + sortBy, а не отдельные копии списка. Стабильный key={task.id} обязателен: key={index} ломает фокус и анимации при удалении.

                        Расширенная модель (приоритет, дедлайн) учит проектировать типы заранее. Просроченные задачи — вычисляемое свойство: deadline < today. Поиск с debounce (hook из недели 13) снижает нагрузку при больших списках. Persist в localStorage через hook сохраняет данные между сессиями.

                        +

                        Мысленная модель useTasks: это единственная «таблица данных» в приложении, а Dashboard и страница /tasks — просто разные «представления» (views) над одной и той же таблицей, как в базе данных. Ни одна страница не имеет своей копии задач — обе читают из одного hook (напрямую или через Context-обёртку), поэтому изменение в одном месте немедленно видно в другом без ручной синхронизации.

                        +

                        Эта архитектура станет буквальным шаблоном для будущей интеграции с backend (недели 21–22): внутри useTasks вызовы localStorage.setItem заменятся на fetch('/api/tasks', { method: 'POST' }), а интерфейс хука — { tasks, addTask, toggleTask, removeTask } — может остаться прежним. Компоненты, которые уже используют этот hook, не заметят разницы. Именно поэтому важно спроектировать интерфейс хука чисто уже сейчас, на учебном localStorage-варианте.

                        +

                        Конкретный пример иммутабельного обновления: toggleTask(id) должен делать setTasks(prev => prev.map(t => t.id === id ? { ...t, done: !t.done } : t)), а не искать задачу и менять task.done = true напрямую. Прямая мутация не только не вызовет ререндер сама по себе, но и незаметно «протухнет» производный state на Dashboard (день 93), который вычисляет статистику из этого же массива — на первый взгляд обновление вроде бы произошло (объект действительно изменился в памяти), но React не увидит новой ссылки и не перерисует использующие эти данные компоненты.

                        +

                        Частое заблуждение — относиться к key={index} как к безобидной формальности, лишь бы убрать warning в консоли. На самом деле при удалении задачи из середины списка все последующие элементы «сдвигают» свои индексы, и React из-за неправильного key может сопоставить старый DOM-узел не с той задачей — в лёгких случаях это просто визуальный глюк, а в более сложных, где TodoItem содержит <input> в режиме редактирования, это приводит к потере фокуса или к тому, что текст редактируется не в той строке, в которой видит пользователь. Стабильный key={task.id} из практики дня — не стилистическая рекомендация, а прямая защита от этого класса багов.

                        Читать:

                        • React — Keys
                        • @@ -210,7 +222,7 @@

                          Практика (лайт / MVP)

                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                          Если застрял

                          -

                          Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                          +

                          Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                          Git

                          
                           cd learning-log/week-14
                          @@ -232,14 +244,18 @@ 

                          Ловушки


                          День 95 (Чт): Weather — интеграция внешнего API

                          -

                          Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                          -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                          +

                          Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                          +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                          Связь с проектом: шаг к React Dashboard

                          Теория

                          Интеграция внешнего API — переход от учебного localStorage к реальному асинхронному миру. OpenWeather Current Weather API принимает город и ключ, возвращает температуру, влажность, описание и код иконки. Единицы (metric / imperial) лучше брать из Settings, а не хардкодить.

                          Три UI-состояния обязательны: loading (skeleton или spinner), error (сообщение + retry), success (данные). Проверяй res.ok — 401 (битый ключ), 404 (город не найден) и 429 (лимит free tier) должны давать понятный текст, а не «белый экран смерти». Кэш в sessionStorage на 10 минут с timestamp экономит квоту API.

                          useFetch или dedicated weatherApi.ts изолируют HTTP от компонента. Мини-виджет на Dashboard и полная страница /weather должны использовать один hook — иначе дублируется логика кэша. Debounce или submit по кнопке: запрос на каждый keystroke в поле города быстро исчерпает лимит.

                          +

                          Мысленная модель API-слоя: weatherApi.ts — это граница, за которой прячутся все детали конкретного сервиса (URL, ключ, формат ответа), а компонент Weather вообще не должен знать, что источник данных — именно OpenWeather, а не какой-то другой провайдер. Если завтра понадобится сменить сервис погоды, меняется только этот файл — UI и hook, которые его используют, остаются нетронутыми.

                          +

                          Это разделение — не абстрактная архитектурная гигиена, а буквально тот же принцип, который появится на неделях 21–22 при подключении собственного backend: компонент вызывает getWeather(city), не зная и не заботясь о том, идёт ли запрос к внешнему API, к своему серверу или пока вообще к моковым данным. Правильно спроектированный weatherApi.ts сегодня — это репетиция будущего apiClient.ts для своих же REST-эндпоинтов.

                          +

                          Конкретный пример квоты: free tier OpenWeather ограничен по количеству запросов в минуту/день. Кэш в sessionStorage с timestamp («если последний ответ для этого города младше 10 минут — используй его, не делай новый запрос») экономит квоту при обычном использовании (повторные заходы на страницу, переключение вкладок) и параллельно ускоряет восприятие — данные появляются мгновенно из кэша, а не после сетевого round-trip.

                          +

                          Частое заблуждение — считать, что fetch сам «выбросит ошибку» при неудачном HTTP-ответе, как это делает, например, axios по умолчанию. На самом деле fetch реджектит промис только при сетевом сбое (нет соединения, DNS не резолвится); ответ с кодом 401 (неверный ключ) или 404 (город не найден) — это полностью «успешный» с точки зрения fetch промис, просто с res.ok === false. Если не проверять res.ok явно и не бросать собственную ошибку, res.json() на теле ошибки OpenWeather ({ cod: 401, message: 'Invalid API key' }) отработает без исключений, и приложение попытается отрисовать погоду из объекта, где температуры попросту нет — это и есть тот самый «белый экран смерти», упомянутый в «Ловушках» дня, и практика явно требует обрабатывать 401/404/429 текстом, понятным пользователю, а не давать приложению упасть в неопределённое состояние.

                          Читать:

                          • OpenWeatherMap Current Weather
                          • @@ -280,7 +296,7 @@

                            Практика (лайт / MVP)

                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                            Если застрял

                            -

                            Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                            +

                            Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                            Git

                            
                             cd learning-log/week-14
                            @@ -302,14 +318,18 @@ 

                            Ловушки


                            День 96 (Пт): Settings — Context и персонализация

                            -

                            Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                            -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                            +

                            Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                            +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                            Связь с проектом: шаг к React Dashboard

                            Теория

                            Settings — центр персонализации и хороший тест на Context. Разделяй ThemeContext и UserContext: смена имени пользователя не должна перерисовывать подписчиков темы. Controlled form синхронизирует поля с state; изменения сразу отражаются на Dashboard и Weather без перезагрузки.

                            useId() генерирует стабильные id для связки label + input — важно для доступности и для избежания коллизий при нескольких формах. Валидация на клиенте (имя ≥ 2 символов, город не пустой) улучшает UX, даже если позже добавишь серверную проверку.

                            Деструктивные действия («Сбросить настройки») требуют confirm dialog. Persist через localStorage в Provider или custom hook. Бонус export/import JSON — учит сериализовать state целиком. Toast при успешном сохранении даёт обратную связь без блокировки UI.

                            +

                            Мысленная модель Settings — это панель управления с несколькими независимыми переключателями, каждый из которых пишет в свой собственный Context, а не в один общий объект настроек. Это прямое практическое испытание урока с недели 13 (день 88): если разделение ThemeContext и UserContext было сделано правильно, ввод имени в форме настроек физически не должен вызывать перерисовку компонентов, подписанных только на тему — это легко проверить, поставив console.log('theme render') внутри компонента-потребителя ThemeContext и понаблюдав, срабатывает ли он при вводе имени.

                            +

                            Такая дисциплина разделения ответственности пригодится в любом реальном приложении с профилем и настройками пользователя — от простого лендинга с личным кабинетом до крупных SaaS-продуктов, где страница настроек — один из самых часто посещаемых и при этом самых «тяжёлых по side effects» экранов.

                            +

                            Конкретный пример независимого persist: смена темы должна сохраняться в localStorage сразу при клике на переключатель (через useEffect внутри ThemeProvider), а смена имени пользователя — при submit формы, а не посимвольно при каждом нажатии клавиши. Смешение этих двух момента persist (когда именно писать в storage) — частый источник лишних записей на диск или, наоборот, потери данных при случайном закрытии вкладки до отправки формы.

                            +

                            Частое заблуждение — думать, что раз useLocalStorage уже был написан на неделе 13, «persist происходит сам по себе» для любых новых данных без дополнительных действий. На самом деле каждый новый кусок state (единицы измерения °C/°F, город по умолчанию) требует либо использования того же useLocalStorage хука явно, либо ручного useEffect, который синхронизирует именно это значение — забытый шаг здесь означает, что настройка «применится сейчас», но пропадёт после F5, что напрямую противоречит критерию дня «настройки переживают перезагрузку». Кнопка «Сбросить настройки» без confirm() — ещё один риск: пользователь может случайно потерять персонализацию одним кликом, поэтому диалог подтверждения — не формальность, а обязательная защита от необратимого действия.

                            Читать:

                            • React — useId
                            • @@ -372,14 +392,18 @@

                              Ловушки


                              День 97 (Сб): Полировка UX и адаптив

                              -

                              Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                              -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                              +

                              Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                              +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                              Связь с проектом: шаг к React Dashboard

                              Теория

                              Полировка UX отличает «работает» от «приятно пользоваться». Адаптив — не опция: начни с 320px ширины, убедись, что нет horizontal scroll. Hamburger-меню на мобиле превращает sidebar в drawer; на desktop — постоянная навигация. Touch targets ≥ 44px снижают mis-tap на телефоне.

                              Доступность: :focus-visible вместо outline: none, tab-навигация по всем интерактивным элементам, контраст текста ≥ WCAG AA (проверь в DevTools). prefers-reduced-motion уважает настройки ОС — отключи лишние анимации для пользователей с вестибулярными расстройствами.

                              Toast-уведомления — лёгкий паттерн feedback при CRUD. Empty states («Нет задач — добавьте первую») лучше пустой таблицы. Lighthouse audit: цель Performance ≥ 80, Accessibility ≥ 90. Микро-анимации через CSS transitions добавляют «живости» без тяжёлых библиотек.

                              +

                              Мысленная модель этого дня: «Definition of Done» для интерфейса включает доступность и мобильную адаптацию по умолчанию, а не как опциональный бонус «если останется время». Полезная привычка — проектировать от 320px вверх (mobile-first), а не тестировать desktop-версию и потом «сжимать» её медиа-запросами: вторая стратегия почти всегда приводит к горизонтальному скроллу и мелкому тексту на реальных телефонах.

                              +

                              Это напрямую влияет на оценку проекта в реальном мире: Lighthouse Accessibility и Performance — метрики, которые смотрят рекрутеры и тимлиды при код-ревью портфолио, а в некоторых юрисдикциях доступность интерфейса — не пожелание, а юридическое требование (WCAG). Мобильный трафик во многих продуктах составляет больше половины пользователей, так что «доделать адаптив потом» на практике означает «сломанный опыт для большинства».

                              +

                              Конкретный пример: outline: none на кнопке без замены полностью убирает визуальную индикацию фокуса — пользователь, управляющий сайтом только клавиатурой (Tab), физически не видит, на каком элементе находится. :focus-visible — правильная замена: она показывает обводку при навигации с клавиатуры, но не мешает эстетике при клике мышью, где фокус менее важен визуально.

                              +

                              Частое заблуждение — тестировать интерфейс только на своём ноутбуке с мышью и считать «выглядит нормально» достаточным критерием готовности. Это никак не проверяет tab-навигацию, touch-target размеры (кнопка 24×24px удобна для курсора, но промахивается пальцем), контраст текста при ярком солнечном свете или вестибулярную нагрузку от резких анимаций у части пользователей — отсюда обязательность prefers-reduced-motion. Практика дня требует явной проверки на 320px и через Lighthouse именно потому, что визуальная проверка «на глаз» систематически пропускает эти категории проблем — это касается и мобильного меню (hamburger → drawer), которое должно быть доступно и с клавиатуры, не только тапом по иконке.

                              Читать:

                              • MDN — Responsive design
                              • @@ -420,7 +444,7 @@

                                Практика (лайт / MVP)

                                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                Если застрял

                                -

                                Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                +

                                Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                Git

                                
                                 cd learning-log/week-14
                                @@ -442,14 +466,18 @@ 

                                Ловушки


                                День 98 (Вс): Тестирование вручную и документация

                                -

                                Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                +

                                Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                Связь с проектом: шаг к React Dashboard

                                Теория

                                React Dashboard — крупнейший фронтенд-проект до бэкенда; день ревью фиксирует качество, а не добавляет фичи. Пройди user flow глазами новичка: первый визит → настройки → задачи → погода → смена темы → F5. Каждый шаг должен работать без инструкции в README.

                                Production build (npm run build) часто выявляет warnings, которые dev-сервер скрывает: неиспользуемые импорты, env без fallback. Deploy на Vercel/Netlify требует настройки SPA fallback для client-side routes. README с GIF или скриншотами — визитная карточка для портфолио.

                                Conventional Commits за неделю показывают зрелость: feat:, fix:, docs: в сообщениях. ARCHITECTURE.md обнови финальной схемой state. Этот проект станет основой для full-stack интеграции на неделях 21–22 — чистая структура сейчас сэкономит часы потом.

                                +

                                Мысленная модель дня ревью: посмотри на свой проект глазами человека, который видит его первый раз и не читал твой код — именно так его увидит рекрутер, тимлид на код-ревью или случайный посетитель портфолио. User flow «первый визит → настройки → задачи → погода → смена темы → F5» — это ручной аналог QA-сценария (test case), который проверяет не отдельные функции, а связность всего приложения как единого продукта.

                                +

                                Привычка проверять npm run build перед тем, как считать день/неделю законченными, — то, что отличает учебный проект от production-ready: dev-сервер Vite нередко прощает вещи, которые ломаются в собранном бандле — например, переменную окружения без fallback-значения, которая в dev была подставлена из .env, а в проде на Vercel забыли настроить, и приложение падает в рантайме с непонятной ошибкой вместо явного сообщения при сборке.

                                +

                                Конкретный пример скрытой проблемы: неиспользуемый импорт компонента, случайно оставленный после рефакторинга, в dev-режиме никак не мешает работе, но при npm run build в strict-конфигурации может всплыть предупреждением, а в некоторых сетапах — и ошибкой, останавливающей деплой; лучше поймать это самому за 5 минут локально, чем через уведомление о падении билда на хостинге.

                                +

                                Частое заблуждение — недооценивать README, считая его формальностью «для галочки». На практике именно README — первое, что видит любой человек, открывший репозиторий (рекрутер за 30 секунд решает, смотреть ли код дальше), и единственный способ показать масштаб проделанной работы без необходимости запускать проект локально. GIF или три скриншота стоят десятков строк текстового описания фичей. Это же качество документации станет частью финального full-stack проекта на неделях 21–22, где React Dashboard, разработанный на этой неделе, получит настоящий backend — и осмысленная git-история с Conventional Commits, начатая уже сейчас, сделает эту интеграцию прослеживаемой, а не хаотичной.

                                Читать:

                                • Conventional Commits
                                • @@ -490,7 +518,7 @@

                                  Практика (лайт / MVP)

                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                  Если застрял

                                  -

                                  Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                  +

                                  Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                  Git

                                  
                                   cd learning-log/week-14
                                  diff --git a/docs/w/15.html b/docs/w/15.html
                                  index 24432ac..817f558 100644
                                  --- a/docs/w/15.html
                                  +++ b/docs/w/15.html
                                  @@ -22,14 +22,18 @@
                                   
                                   

                                  День 99 (Пн): Установка, синтаксис, venv

                                  -

                                  Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                  -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                  +

                                  Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                  +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                  Связь с проектом: шаг к CLI Expense Tracker

                                  Теория

                                  Python — первый шаг в backend после фронтенда. Установка с python.org (или py launcher на Windows) и проверка python --version — база. Главная привычка с первого дня: виртуальное окружение python -m venv .venv изолирует зависимости проекта от системного Python. Без активации venv пакеты ставятся глобально и ломают другие проекты.

                                  Синтаксис Python читается почти как псевдокод: отступы (4 пробела, PEP 8) — часть языка, не стиль. Типы: int, float, str, bool, None. f-strings (f"Привет, {name}") — современный способ форматирования. input() всегда возвращает строку — для чисел нужен int() или float() с обработкой ValueError.

                                  Операторы // (целочисленное деление) и % (остаток) пригодятся в задачах. REPL (python без аргументов) — быстрая проверка выражений. python -m pip install ставит пакеты в активный venv. Shebang #!/usr/bin/env python3 полезен для скриптов на Unix, на Windows — вторично.

                                  +

                                  Мысленная модель venv: это то же самое, что node_modules в мире Node.js, но для Python нужно создавать его явно, потому что интерпретатор по умолчанию один на всю систему, а не «per project», как в JS-экосистеме с локальными зависимостями из коробки. python -m venv .venv создаёт изолированную копию интерпретатора и пространство для пакетов именно этого проекта — активация переключает python и pip на эту копию, деактивация возвращает к системной версии.

                                  +

                                  Привычка, сформированная сегодня, будет использоваться в каждом Python-проекте до конца курса: без venv два учебных проекта, которым нужны разные версии одной библиотеки, начнут конфликтовать в системном Python, а на реальной работе разные сервисы одной компании почти гарантированно требуют разных версий одних и тех же зависимостей.

                                  +

                                  Конкретный пример конфликта: проект A на неделе 15 использует rich==13.0, а гипотетический проект B — rich==14.0 с другим API. Без venv установка пакета для проекта B перезапишет глобальную версию и сломает проект A при следующем запуске — оба будут молча использовать не ту версию библиотеки, для которой писался код.

                                  +

                                  Частое заблуждение — считать, что установка «всего одного пакета» без активного venv не страшна, потому что «он маленький» или «я потом уберу». На практике такие исключения накапливаются: через несколько недель системный Python оказывается захламлён десятками пакетов из разных мини-экспериментов, версии конфликтуют между собой, а диагностировать, какой пакет откуда взялся, почти невозможно. Именно поэтому в критериях дня явно указано «venv активирован, зависимости не в global Python» — это не бюрократическая формальность, а страховка от часов будущей отладки при работе над hello.py и calculator.py, где пока используются только встроенные возможности языка, но привычка ставится с первого файла.

                                  Читать:

                                  • Installing Python
                                  • @@ -92,14 +96,18 @@

                                    Ловушки


                                    День 100 (Вт): Условия, циклы, comprehensions

                                    -

                                    Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                    -Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                    +

                                    Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                    +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                    Связь с проектом: шаг к CLI Expense Tracker

                                    Теория

                                    Условия и циклы — скелет любой программы. if/elif/else опирается на truthiness: пустой список [], строка "", ноль 0 и None — falsy. Это отличается от JavaScript, где только некоторые значения falsy. Циклы for итерируют по итерируемым объектам; while — пока условие истинно; break и continue управляют потоком.

                                    range(n) генерирует последовательность без создания списка в памяти. enumerate(items) даёт пары (индекс, элемент) — идиоматичнее, чем for i in range(len(items)). zip(a, b) объединяет два списка попарно. У цикла for есть необязательный else, выполняющийся, если не было break — редкий, но полезный приём.

                                    List comprehension [x**2 for x in range(10) if x % 2 == 0] компактно строит список. Не увлекайся вложенностью — читаемость важнее одной строки. Walrus := (3.8+) присваивает в выражении. Не изменяй список во время итерации по нему — пропустишь элементы.

                                    +

                                    Мысленная модель list comprehension: это декларативное «что» вместо императивного «как». Обычный цикл for описывает пошаговый процесс («иди по каждому элементу, проверяй условие, добавляй в новый список»); comprehension [x**2 for x in range(10) if x % 2 == 0] описывает сразу результат — «список квадратов чётных чисел от 0 до 9» — и читается почти как математическая нотация множества. Это не просто короче — это другой способ мышления о трансформации данных, который окажется повсюду в реальном Python-коде: обработка данных, фильтрация запросов к БД в Django ORM использует концептуально похожий стиль.

                                    +

                                    Понимание truthiness критично именно потому, что ты уже знаком с JavaScript и подсознательно можешь перенести не те правила: в Python 0, 0.0, "", [], {}, None и False — falsy, всё остальное — truthy, и в этом Python на самом деле почти как JS. Но есть тонкость: в JS NaN тоже falsy, а в Python отдельного «falsy NaN» с таким поведением нет — сравнения устроены иначе, и полагаться на интуицию из JS без проверки документации рискованно.

                                    +

                                    Конкретный пример: проверка пустого списка задач if not tasks: — идиоматичный Python, эквивалентный по смыслу if (tasks.length === 0) в JS, но синтаксически основанный именно на truthiness пустой коллекции, а не на явном сравнении длины.

                                    +

                                    Частое заблуждение — писать if tasks == []: вместо if not tasks:, что технически работает, но не идиоматично и не сработает единообразно для других falsy-коллекций ({}, set()). Ещё одна ошибка, специфичная для новичков с опытом в JS, — изменять список прямо во время итерации по нему (for item in items: items.remove(item)), что в Python приводит к пропуску элементов из-за сдвига индексов внутри итератора, а не к очевидной ошибке — именно это явно указано в «Ловушках» дня и стоит проверить на практике при написании FizzBuzz и задач с comprehension.

                                    Читать:

                                    • List comprehensions
                                    • @@ -140,7 +148,7 @@

                                      Практика (лайт / MVP)

                                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                      Если застрял

                                      -

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

                                      +

                                      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                      Git

                                      
                                       cd learning-log/week-15
                                      @@ -162,14 +170,18 @@ 

                                      Ловушки


                                      День 101 (Ср): Функции и type hints

                                      -

                                      Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                      +

                                      Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                      +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                      Связь с проектом: шаг к CLI Expense Tracker

                                      Теория

                                      Функции в Python — первый уровень абстракции. def name(args) -> return_type: с type hints документирует контракт для IDE и будущего mypy. Docstring в тройных кавычках (PEP 257) объясняет назначение, аргументы и возвращаемое значение. if __name__ == "__main__": отделяет точку входа от импортируемого модуля.

                                      Аргументы по умолчанию должны быть immutable: def f(x=[]) — антипаттерн, один список на все вызовы. Используй None и создавай список внутри. *args собирает позиционные аргументы, **kwargs — именованные. После * в сигнатуре — только keyword-only аргументы.

                                      Чистые функции (без side effects) проще тестировать: celsius_to_fahrenheit(0) всегда даёт 32.0. Функция без return неявно возвращает None — частая ловушка. Scope: избегай global, передавай данные аргументами.

                                      +

                                      Мысленная модель функции с type hints: сигнатура — это контракт, который читают не только люди, но и инструменты. def celsius_to_fahrenheit(c: float) -> float: сообщает IDE, что автодополнение и подсказки типов работают для параметра и результата, а mypy может статически проверить, что функция нигде не вызывается с неверным типом — задолго до того, как ошибка проявится в рантайме. Docstring в тройных кавычках — та же идея для смысла: не «что делает код», а «что обещает функция», включая крайние случаи.

                                      +

                                      Эта дисциплина станет строго необходимой позже: любой современный Python backend-фреймворк (FastAPI, с которым познакомишься в конце курса) строит валидацию запросов и автогенерацию документации API прямо на type hints — то есть привычка, выработанная сегодня на простых функциях вроде format_currency, напрямую превратится в рабочий навык для реальных веб-сервисов.

                                      +

                                      Конкретный пример mutable default argument: def add_item(item, bag=[]): bag.append(item); return bag. Кажется, что каждый вызов получает свежий пустой список, но список [] в сигнатуре создаётся один раз, в момент определения функции, а не при каждом вызове — поэтому второй вызов add_item('apple') без явного bag вернёт список, в котором уже лежит результат первого вызова, что выглядит как необъяснимая утечка состояния между полностью независимыми вызовами функции.

                                      +

                                      Частое заблуждение — переносить в Python интуицию из языков, где значение по умолчанию действительно вычисляется заново при каждом вызове функции; в Python дефолтное значение — это выражение, вычисленное ровно один раз при объявлении def, и если это изменяемый объект (список, словарь, множество), он становится общим для всех вызовов, где аргумент не передан явно. Правильный паттерн — def add_item(item, bag=None): bag = bag if bag is not None else [] — обсуждается прямо в «Ловушках» дня и должен быть применён при реализации utils.py и CLI-конвертера валют, где список курсов или история конвертаций легко могли бы попасть в эту же ловушку.

                                      Читать:

                                      • Defining Functions
                                      • @@ -210,7 +222,7 @@

                                        Практика (лайт / MVP)

                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                        Если застрял

                                        -

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

                                        +

                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                        Git

                                        
                                         cd learning-log/week-15
                                        @@ -232,14 +244,18 @@ 

                                        Ловушки


                                        День 102 (Чт): Структуры данных — list, tuple, dict, set

                                        -

                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                        -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                        +

                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                        +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                        Связь с проектом: шаг к CLI Expense Tracker

                                        Теория

                                        Выбор структуры данных определяет скорость и читаемость кода. list — упорядоченная изменяемая коллекция: append, extend, срезы lst[1:3], сортировка in-place (sort) или новый список (sorted). dict — словарь по hashable-ключам: lookup в среднем O(1) против O(n) у списка. .get(key, default) безопаснее прямого dict[key].

                                        set хранит уникальные элементы и поддерживает union, intersection, difference — удобно для удаления дубликатов. tuple неизменяем: подходит для координат, записей из БД, ключей словаря. collections.Counter ускоряет подсчёт частот. Копирование: copy.copy — shallow, copy.deepcopy — вложенные структуры.

                                        Телефонная книга на dict[name] = phone — классический CRUD. Список нельзя использовать как ключ dict (unhashable). Для сортировки списка словарей: sorted(items, key=lambda x: x['score']).

                                        +

                                        Мысленная модель выбора структуры данных: это выбор алгоритмической сложности заранее, а не после того, как программа начнёт тормозить. dict — это hash map: поиск по ключу в среднем O(1) независимо от размера словаря, потому что Python вычисляет хеш ключа и сразу переходит к нужной ячейке памяти. list — это последовательность: поиск конкретного элемента требует в среднем прохода по половине элементов, то есть O(n) — при 10 записях разница незаметна, при 100 000 — принципиальна.

                                        +

                                        Эта интуиция станет фундаментом для куда более серьёзных решений в будущем: при работе с базами данных (позже в курсе) индекс на колонке — это буквально то же самое hash map/B-tree ускорение, что и dict здесь, только на уровне СУБД, а не языка. Понимание, почему dict.get(key) быстрее [x for x in list if x.name == key], напрямую переносится на понимание, зачем в SQL вообще нужны индексы.

                                        +

                                        Конкретный пример: телефонная книга на 10 000 контактов, реализованная как list[dict], требует перебора в среднем 5000 записей на каждый поиск по имени. Та же книга как dict[name] = phone находит контакт за одну операцию хеширования, вне зависимости от того, 10 там записей или миллион — разница становится ощутимой на практике уже при тысячах контактов, а не только в теории алгоритмов.

                                        +

                                        Частое заблуждение — переносить из JS привычку использовать массивы (list) для всего подряд просто потому, что это самая знакомая структура, не задумываясь о паттерне доступа к данным. Другая тонкость: dict в CPython 3.7+ гарантированно сохраняет порядок вставки ключей, а вот set — нет, это неупорядоченная коллекция, и полагаться на «естественный» порядок при переборе set — источник трудноуловимых различий в поведении между запусками. Именно поэтому реализация телефонной книги в практике дня выбирает dict[name] = phone, а не список словарей — это не произвольная стилистика, а прямое следствие паттерна доступа «найти контакт по точному имени».

                                        Читать:

                                        • Data structures
                                        • @@ -280,7 +296,7 @@

                                          Практика (лайт / MVP)

                                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                          Если застрял

                                          -

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

                                          +

                                          Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                          Git

                                          
                                           cd learning-log/week-15
                                          @@ -302,14 +318,18 @@ 

                                          Ловушки


                                          День 103 (Пт): Работа с файлами и JSON

                                          -

                                          Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                          -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                          +

                                          Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                          +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                          Связь с проектом: шаг к CLI Expense Tracker

                                          Теория

                                          Файлы и JSON — мост между программой и диском. Context manager with open(path, 'r', encoding='utf-8') as f: гарантирует закрытие файла даже при исключении. На Windows encoding='utf-8' критичен для кириллицы. Режимы: r чтение, w перезапись, a дополнение в конец.

                                          Модуль json: load/dump для файлов, loads/dumps для строк. ensure_ascii=False сохраняет Unicode, indent=2 делает файл читаемым для человека. Обрабатывай FileNotFoundError (первый запуск) и JSONDecodeError (битый файл) — graceful start важнее краша.

                                          pathlib.Path — современная альтернатива строковым путям: Path('data') / 'contacts.json'. Atomic write (запись во временный файл + rename) защищает от потери данных при сбое. Для отладки — print, для production — модуль logging с уровнями.

                                          +

                                          Мысленная модель with open(...) as f: — это гарантия, а не просто удобный синтаксис: контекстный менеджер гарантированно закроет файл (и сбросит буфер записи на диск) даже если между открытием и закрытием произойдёт исключение. Без with пришлось бы вручную оборачивать код в try/finally с явным f.close(), и забытый close() в реальных программах — частая причина «файл вроде записался, но данные потерялись» из-за того, что операционная система буферизует запись и не обязана сбрасывать её на диск немедленно.

                                          +

                                          JSON-файл в этом контексте — это сериализованный снимок состояния программы между запусками: contacts.json — не просто «файл с данными», а контракт, который читает и пишет твоя программа при каждом старте и завершении. Тот же принцип (сериализация состояния в текстовый формат для передачи или хранения) станет центральным чуть позже в курсе, когда JSON превратится в формат тела HTTP-запросов и ответов между фронтендом и backend — сегодняшнее упражнение с файлом на диске концептуально то же самое, что будущий API-запрос, только без сети.

                                          +

                                          Конкретный пример скрытой проблемы: на Windows чтение файла без явного encoding='utf-8' может использовать системную кодировку (часто cp1251 для русской локали), из-за чего кириллица в contacts.json превращается в кракозябры не сразу с ошибкой, а тихо — файл открывается, что-то читается, программа не падает, но данные повреждены, и заметить это можно далеко не сразу, особенно если тестировать только с латиницей.

                                          +

                                          Частое заблуждение — думать, что f.write(data) мгновенно физически записывает байты на диск и что если сразу после write() выключить компьютер или убить процесс, данные точно сохранятся. На самом деле между write() и физической записью на диск стоит буфер операционной системы, и именно закрытие файла (явное или через выход из блока with) инициирует его сброс. В критериях дня явно указано «graceful handling если файл не существует» и «ensure_ascii=False для кириллицы» — оба пункта напрямую защищают от описанных выше проблем при реализации persist телефонной книги в JSON.

                                          Читать:

                                          • Reading and Writing Files
                                          • @@ -372,14 +392,18 @@

                                            Ловушки


                                            День 104 (Сб): Модули, пакеты, pip

                                            -

                                            Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                            -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                            +

                                            Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                            +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                            Связь с проектом: шаг к CLI Expense Tracker

                                            Теория

                                            Модули и пакеты масштабируют код за пределы одного файла. import module и from package import name — два стиля; второй удобнее, но может засорить namespace. Пакет — папка с __init__.py (в Python 3.3+ namespace packages возможны без него, но для учебных проектов __init__.py явно). __all__ объявляет публичный API пакета.

                                            pip install package ставит зависимости в venv; pip freeze > requirements.txt фиксирует версии для воспроизводимых сборок. Pin versions (rich==13.x.x) защищает от неожиданных breaking changes. PyPI — реестр пакетов: requests, rich и тысячи других.

                                            Запуск python -m phonebook.cli выполняет модуль как скрипт с корректными относительными импортами. Избегай циклических импортов: models не должен импортировать cli. Не называй файл json.py — затенишь стандартный модуль.

                                            +

                                            Мысленная модель пакета: это граница пространства имён плюс явно объявленный публичный API. Папка с __init__.py — не формальность, а сигнал Python «это единый модуль, а не просто набор файлов рядом», а __all__ внутри __init__.py явно перечисляет, что видно снаружи пакета, а что — внутренняя деталь реализации, которую пользователи пакета не должны трогать напрямую.

                                            +

                                            Разделение на models.py (структуры данных), storage.py (чтение/запись) и cli.py (взаимодействие с пользователем) — это не искусственное упражнение, а миниатюрная версия слоистой архитектуры, которая будет использоваться в любом более крупном приложении: тот же принцип «данные отдельно от способа их хранения, отдельно от интерфейса» лежит в основе backend-фреймворков вроде Django (models/views/serializers) и FastAPI (schemas/crud/routers), с которыми ты столкнёшься позже в курсе.

                                            +

                                            Конкретный пример пользы requirements.txt с зафиксированными версиями: если сегодня установлен rich==13.7.0, а через полгода на новой машине без pinned версии автоматически поставится rich==14.x с изменённым API, скрипт может сломаться без единого изменения в собственном коде — просто потому что зависимость обновилась. pip freeze > requirements.txt фиксирует не только сам факт использования библиотеки, но и точную версию, гарантируя воспроизводимость окружения на любой машине и через любое время.

                                            +

                                            Частое заблуждение — переносить из JS-опыта расслабленное отношение к порядку импортов, где циклические зависимости между модулями иногда «просто работают» из-за особенностей резолвинга ES-модулей или бандлера. В Python циклический импорт (models.py импортирует что-то из cli.py, а cli.py — из models.py) на практике почти гарантированно приводит к ImportError: cannot import name ... (most likely due to a circular import), потому что модуль в момент своего первого импорта ещё не полностью выполнен. Именно поэтому «Ловушки» дня явно требуют однонаправленной иерархии зависимостей (models не импортирует cli) — это правило стоит соблюдать с самого начала разбиения телефонной книги на пакет phonebook/, а не исправлять постфактум, когда импорты уже переплетены.

                                            Читать:

                                            • Modules
                                            • @@ -421,7 +445,7 @@

                                              Практика (лайт / MVP)

                                              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                              Если застрял

                                              -

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

                                              +

                                              Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                              Git

                                              
                                               cd learning-log/week-15
                                              @@ -443,14 +467,18 @@ 

                                              Ловушки


                                              День 105 (Вс): Ревью основ Python

                                              -

                                              Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                              -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                              +

                                              Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                              +Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                              Связь с проектом: шаг к CLI Expense Tracker

                                              Теория

                                              Ревью недели закрепляет фундамент перед CLI Expense Tracker. PEP 8 — не догма, а общий язык: snake_case для функций и переменных, 79–88 символов в строке, два пустых ряда между top-level определениями. python -m py_compile file.py проверяет синтаксис без запуска.

                                              Сравни Python с JavaScript: отступы вместо {}, None вместо null, иная truthiness, явный self в методах. HackerRank/Codewars на Easy уровне тренируют синтаксис вне контекста проекта. Шпаргалка list vs tuple vs dict vs set — шпаргалка на всю карьеру.

                                              CLI Expense Tracker объединяет всё: venv, модули, JSON persist, rich для таблиц, валидацию ввода. README с примерами команд — обязателен. Осмысленные коммиты за 7 дней и тег week-15-done завершают неделю.

                                              +

                                              Мысленная модель PEP 8: это не эстетическое предпочтение, а общий словарь, снижающий когнитивную нагрузку при чтении чужого (и своего же, через месяц) кода. Когда весь код в индустрии более-менее следует одним соглашениям (snake_case, отступы, пустые строки между определениями), разработчик тратит меньше усилий на «расшифровку» стиля и больше — на понимание логики. Это станет заметно уже при работе в команде или ревью чужого pull request.

                                              +

                                              Явное сравнение Python и JavaScript, предложенное сегодня, помогает не «смешать» две ментальные модели в одну кашу, а держать их четко разделёнными: явный self первым параметром метода в Python — это осознанный дизайн (в отличие от неявного и местами запутанного this в JS, зависящего от способа вызова функции), и понимание этой разницы предотвращает перенос интуиции о this/биндинге туда, где она не работает.

                                              +

                                              Конкретный пример пользы практики на HackerRank/Codewars именно сейчас: задачи вне контекста проекта тренируют синтаксис и стандартную библиотеку (sorted, Counter, slicing) в чистом виде, без сопутствующей сложности организации файлов — это как оттачивание отдельных технических приёмов гитариста гаммами, отдельно от разучивания целой песни, коей является Expense Tracker.

                                              +

                                              Частое заблуждение — считать PEP 8 «чисто косметическим» и откладывать форматирование на «потом», а также думать, что раз JavaScript уже знаком, Python-специфичные особенности (truthiness, mutable defaults, is vs ==, единый self) не заслуживают отдельного внимания и «разберутся по ходу». На практике именно эти синтаксические различия — источник большинства мелких, но раздражающих багов у разработчиков, переходящих с JS на Python, а рефакторинг телефонной книги по PEP 8 в практике сегодняшнего дня — не формальность, а шанс закрепить оба набора привычек до того, как начнётся более сложный CLI Expense Tracker, где путаница между двумя языковыми моделями будет стоить дороже времени на исправление.

                                              Читать:

                                              • PEP 8
                                              • @@ -491,7 +519,7 @@

                                                Практика (лайт / MVP)

                                                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                Если застрял

                                                -

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

                                                +

                                                Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                Git

                                                
                                                 cd learning-log/week-15
                                                diff --git a/docs/w/16.html b/docs/w/16.html
                                                index d298266..06c9a17 100644
                                                --- a/docs/w/16.html
                                                +++ b/docs/w/16.html
                                                @@ -22,14 +22,17 @@
                                                 
                                                 

                                                День 106 (Пн): Классы и объекты

                                                -

                                                Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                +

                                                Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                Связь с проектом: шаг к CLI Task Manager

                                                Теория

                                                Объектно-ориентированное программирование в Python объединяет данные и поведение в одной сущности — классе. class BankAccount: с методом __init__(self, ...) инициализирует экземпляр; self — ссылка на конкретный объект. Атрибуты экземпляра (self.balance) хранят состояние; атрибуты класса (currency = 'RUB') — общие настройки для всех счетов.

                                                Три вида методов: обычные (работают с self), @classmethod (альтернативные конструкторы, фабрики), @staticmethod (утилиты без доступа к экземпляру). __str__ — для пользователя (print(account)), __repr__ — для отладки в REPL, должен однозначно идентифицировать объект.

                                                Инкапсуляция в Python — соглашение: префикс _balance сигнализирует «не трогай снаружи», @property даёт контролируемое чтение без прямой мутации. Type hints на методах помогают IDE ловить ошибки до запуска. Баланс меняется только через deposit и withdraw — это и есть защита инвариантов.

                                                +

                                                Полезная ментальная модель: класс — это чертёж, а объект — конкретное здание, построенное по этому чертежу. Чертёж один, зданий может быть тысячи, и каждое хранит собственное состояние в self.__dict__, не разделяя его с соседями. Атрибуты класса (currency = 'RUB') — это табличка на воротах всего микрорайона: изменишь её через класс — увидят все объекты сразу. Именно поэтому mutable атрибут класса (список, словарь по умолчанию) — частая причина неожиданных багов: все экземпляры незаметно «делят» одну и ту же коллекцию, если её не создать в __init__.

                                                +

                                                Эта конструкция не абстрактное упражнение ради экзамена: ровно тот же синтаксис class + __init__ + self появится в моделях SQLAlchemy на неделе 18 (class Book(Base): id: Mapped[int]) и в Pydantic-схемах FastAPI — ООП станет языком, на котором описана вся архитектура backend. На примере BankAccount: вызов acc.deposit(100) под капотом эквивалентен BankAccount.deposit(acc, 100)self это просто первый позиционный аргумент, который Python автоматически подставляет при обращении через точку.

                                                +

                                                Частое заблуждение новичков — считать @staticmethod и @classmethod взаимозаменяемыми. staticmethod не получает ни self, ни cls и годится для чистых утилит (BankAccount.validate_amount(100)); classmethod получает cls и чаще служит альтернативным конструктором (Account.from_dict(data)), который должен корректно работать и для наследников. Ещё одна ловушка — путать __str__ и __repr__: если определить только __repr__, print(obj) использует именно его, но для логов и REPL желательно, чтобы repr можно было почти дословно вставить обратно в код как валидное выражение. В практике дня это проверяется напрямую: __repr__ для Transaction должен однозначно показывать id, сумму и тип — иначе баг по логу не найти.

                                                Читать:

                                                • Classes
                                                • @@ -73,14 +76,17 @@

                                                  Ловушки


                                                  День 107 (Вт): Наследование, композиция, dataclasses

                                                  -

                                                  Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                  -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                  +

                                                  Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                  +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                  Связь с проектом: шаг к CLI Task Manager

                                                  Теория

                                                  Наследование (class Savings(BankAccount)) расширяет базовый класс: дочерний получает методы родителя и добавляет свои. super().__init__(...) вызывает конструктор родителя — забудешь, и поля родителя не инициализируются. Но глубокие иерархии хрупки: предпочитай композицию («has-a»), когда объект содержит другие объекты, а не наследует их («is-a»).

                                                  Portfolio с list[Account] — композиция: портфель не «является» счётом, он их «содержит». Это гибче, чем class Portfolio(Account). @dataclass автогенерирует __init__, __repr__, __eq__ для DTO без сложного поведения — идеально для Expense или Task.

                                                  __post_init__ валидирует поля после создания dataclass (сумма > 0). frozen=True делает объект immutable — безопасен как ключ dict. ABC (ABC, @abstractmethod) задаёт контракт для TaskRepository — подкласс обязан реализовать методы.

                                                  +

                                                  Ментальная модель для выбора между наследованием и композицией — LEGO-конструктор. Наследование — это «разблокировать улучшенную версию детали» с дополнительными способностями родителя (SavingsAccount умеет всё, что умеет BankAccount, плюс начисление процентов). Композиция — это «собрать модель из готовых независимых деталей» (Portfolio не является счётом, он содержит счета). Правило Liskov: наследуй только тогда, когда дочерний объект можно подставить всюду, где ожидается родительский, не сломав поведение. Если такой подстановки нет — это не «is-a», а признак того, что нужна композиция.

                                                  +

                                                  Почему это важно позже: абстрактный BaseRepository с @abstractmethod get/add/delete, который ты создаёшь сегодня, — это тот же паттерн, что и Repository/Service слои в FastAPI-проекте недели 18 и layered-архитектура Express на неделе 19. Понимание ABC-контракта здесь напрямую объясняет, зачем в будущем API определяют интерфейсы, которые обязаны реализовать разные backend'ы (SQLite сегодня, PostgreSQL завтра).

                                                  +

                                                  Частая ошибка новичков — наследовать ради переиспользования кода, а не ради логической связи «is-a», что приводит к глубоким и хрупким иерархиям (Manager(Employee(Person)) с десятком переопределённых методов). Другая типичная ловушка — забыть super().__init__(...) в дочернем классе: тогда поля родителя просто не инициализируются, и на первый взгляд валидный код падает с AttributeError при первом обращении к унаследованному атрибуту. В практике дня это проверяется прямо: SavingsAccount должен вызывать super().__init__() и при этом оставаться взаимозаменяемым с обычным BankAccount везде, где ожидается счёт. Практическое правило для выбора: если ответ на вопрос «B — это разновидность A?» звучит естественно на русском языке, скорее всего перед тобой наследование; если естественнее звучит «B содержит/использует A», выбирай композицию.

                                                  Читать:

                                                  • Inheritance
                                                  • @@ -111,7 +117,7 @@

                                                    Практика (лайт / MVP)

                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                    Если застрял

                                                    -

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

                                                    +

                                                    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                    Git

                                                    • Закоммить изменения дня: git add week-16/git commit -m "week 16 day 107: inheritance, composition, dataclasses"
                                                    • @@ -124,14 +130,17 @@

                                                      Ловушки


                                                      День 108 (Ср): Магические методы и итераторы

                                                      -

                                                      Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                      -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                      +

                                                      Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                      +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                      Связь с проектом: шаг к CLI Task Manager

                                                      Теория

                                                      Магические методы (dunder) делают объекты «питоничными»: __len__ для len(obj), __getitem__ для obj[i], __contains__ для x in obj. Класс Playlist с этими методами ведёт себя как встроенная коллекция — пользователь API не знает о внутреннем list.

                                                      Итератор-протокол: __iter__ возвращает объект с __next__, который выдаёт элементы или бросает StopIteration. Generator function с yield — ленивая последовательность: fibonacci(n) не хранит весь ряд в RAM. Generator read_log_lines(path) читает файл построчно — O(1) память на строку.

                                                      __eq__ определяет равенство; если переопределяешь его и хочешь использовать объекты в set/dict, продумай __hash__ (или используй frozen dataclass). __lt__ позволяет sorted(transactions) без key-функции.

                                                      +

                                                      Ментальная модель: dunder-методы — это «розетки» единого стандарта Python. Реализуешь __len__, __getitem__, __iter__ — и твой объект тут же подключается к экосистеме len(), циклов for, срезов, распаковки, как электроприбор со стандартной вилкой вместо самодельного разъёма. Пользователю Playlist не нужно знать, что внутри list — он просто пишет for track in playlist, как для любой встроенной коллекции.

                                                      +

                                                      Это важно позже: итератор-протокол лежит в основе курсоров баз данных — результат SQL-запроса в SQLAlchemy (неделя 18) и pool.query() в Node (неделя 19) тоже по сути итерируемые последовательности строк. А ленивые generator'ы — прямой путь к обработке данных, которые не помещаются в память целиком: тот же приём понадобится при построчном парсинге логов (день 111) и при потоковой отдаче больших файлов из API.

                                                      +

                                                      Частое заблуждение — думать, что generator можно «перемотать» и пройти повторно: после первого полного обхода for x in fibonacci(10) генератор исчерпан, второй for по тому же объекту ничего не вернёт — нужно создавать новый вызов функции-генератора заново. Также важно не путать __eq__ без согласованного __hash__: если переопределить только __eq__, объект по умолчанию становится unhashable, и попытка положить его в set бросит TypeError — это прямо проверяется в критериях практики дня. Хорошее эмпирическое правило: если объект по смыслу — коллекция или последовательность, реализуй __len__/__iter__, а не заставляй пользователя лезть во внутренний атрибут через playlist.tracks — так API остаётся стабильным, даже если внутреннее хранилище позже сменится с list на что-то другое. Generator function с yield стоит воспринимать как функцию, которая «замораживается» после каждого значения и продолжает выполнение ровно с того места, где остановилась, при следующем вызове next() — в этом смысле она куда ближе к сопрограмме, чем к обычной функции, возвращающей единственный результат.

                                                      Читать:

                                                      • Emulating container types
                                                      • @@ -162,7 +171,7 @@

                                                        Практика (лайт / MVP)

                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                        Если застрял

                                                        -

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

                                                        +

                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                        Git

                                                        • Закоммить изменения дня: git add week-16/git commit -m "week 16 day 108: dunder methods and generators"
                                                        • @@ -175,14 +184,17 @@

                                                          Ловушки


                                                          День 109 (Чт): Алгоритмы и Big O

                                                          -

                                                          Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                          -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                          +

                                                          Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                          +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                          Связь с проектом: шаг к CLI Task Manager

                                                          Теория

                                                          Big O описывает, как растёт время или память при увеличении входа, а не абсолютные миллисекунды. O(1) — константа, O(log n) — бинарный поиск, O(n) — один проход, O(n log n) — эффективная сортировка, O(n²) — вложенные циклы. Выбор структуры данных важнее микрооптимизаций: dict lookup O(1) в среднем vs list O(n).

                                                          Linear search перебирает все элементы; binary search требует отсортированный массив и делит пополам — O(log n). На 10⁶ элементов разница колоссальна. Two Sum: brute force O(n²) vs hash map O(n) — классический пример, когда дополнительная память покупает скорость.

                                                          Встроенная сортировка Python (Timsort) — O(n log n); bubble sort O(n²) — учебный, не production. list.append амортизированно O(1), но иногда O(n) при resize. VisuAlgo помогает увидеть рост операций. Замеры через time.perf_counter() убеждают лучше теории.

                                                          +

                                                          Ментальная модель Big O — это не секундомер, а вопрос «как растёт очередь в кассе, если покупателей стало в 10 раз больше». O(1) — очередь не меняется независимо от числа покупателей (хеш-таблица); O(n) — очередь растёт пропорционально (один проход по списку); O(n²) — при удвоении входа время растёт вчетверо (вложенные циклы, попарные сравнения). Асимптотика описывает поведение на больших n, а не абсолютные миллисекунды на конкретной машине.

                                                          +

                                                          Почему это критично для следующей недели: индекс в PostgreSQL (день 117) — это ровно превращение поиска из O(n) (полный перебор, Seq Scan) в O(log n) (B-tree, Index Scan). Без сегодняшнего понимания разницы между линейным и логарифмическим ростом объяснение EXPLAIN ANALYZE останется магией, а с ним — станет очевидным фактом.

                                                          +

                                                          Частое заблуждение — думать, что алгоритм с лучшей асимптотикой всегда быстрее на практике: у O(n log n) может быть больший constant factor, и на маленьких n (скажем, 20 элементов) простой O(n²) bubble sort иногда обгоняет сложную сортировку из-за накладных расходов. Другая ошибка — путать best/average/worst case, говоря «O(n)» про алгоритм, который в худшем случае деградирует до O(n²) (как naive quicksort на отсортированном входе). В практике дня это проверяется замерами: разница между linear и binary search становится заметной именно на больших объёмах — 10⁶ элементов, а не 10. Two Sum — хороший тест на этот сдвиг мышления: наивное решение перебирает все пары чисел (O(n²)), а решение через хеш-таблицу проходит по массиву один раз, на каждом шаге проверяя, не встречалось ли уже нужное дополнение — обмен памяти (дополнительный словарь) на скорость (O(n)) в чистом виде.

                                                          Читать:

                                                          • Big O Cheat Sheet
                                                          • @@ -213,7 +225,7 @@

                                                            Практика (лайт / MVP)

                                                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                            Если застрял

                                                            -

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

                                                            +

                                                            Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                            Git

                                                            • Закоммить изменения дня: git add week-16/git commit -m "week 16 day 109: Big O benchmarks and Two Sum"
                                                            • @@ -226,14 +238,17 @@

                                                              Ловушки


                                                              День 110 (Пт): pathlib и работа с файловой системой

                                                              -

                                                              Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                              -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                              +

                                                              Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                              +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                              Связь с проектом: шаг к CLI Task Manager

                                                              Теория

                                                              pathlib.Path — объектный API для путей вместо конкатенации строк и os.path.join. Оператор / склеивает кроссплатформенно: Path('data') / 'tasks.db'. read_text(), write_text(), exists(), glob('*.py'), rglob('**/*.py') покрывают 90% задач с файловой системой.

                                                              Path(__file__).parent даёт каталог скрипта — надёжнее относительных путей от cwd, который меняется при запуске из другой папки. shutil.copy, move, rmtree — операции над деревом. Context manager with path.open() гарантирует закрытие файла.

                                                              Скрипт organize.py сортирует файлы по расширению — практика обхода директорий. --dry-run показывает план без изменений — хорошая привычка для деструктивных операций. PermissionError на системных файлах логируй, не падай целиком.

                                                              +

                                                              Ментальная модель: Path — не строка, а объект-значение, описывающий местоположение, а не сам файл. Операции над ним (/, .parent, .suffix) собирают новый путь, не трогая диск, пока явно не вызван read_text(), write_text() или unlink(). Это разделение «описать путь» и «выполнить операцию с файлом» снижает риск случайных побочных эффектов по сравнению со строковой конкатенацией os.path.join.

                                                              +

                                                              Почему это пригодится дальше: путь к SQLite-файлу проекта этой недели (data/tasks.db), путь к статике в FastAPI-приложении недели 18, путь к файлу конфигурации в Express на неделе 19 — везде нужен надёжный якорь Path(__file__).parent, который не зависит от того, откуда запущен скрипт. Привычка мыслить путями как объектами, а не строками, переносится в любой стек, включая pathlib-аналоги в других языках.

                                                              +

                                                              Частое заблуждение — думать, что path.write_text() или shutil.move() создадут промежуточные папки автоматически: если родительской директории нет, операция упадёт с FileNotFoundError, и нужно явно вызвать path.parent.mkdir(parents=True, exist_ok=True). Ещё одна типичная ошибка — полагаться на относительные пути от текущей директории запуска (Path('data/tasks.db')), которая меняется в зависимости от того, откуда вызван скрипт — отсюда обязательность --dry-run в практике: он заставляет сначала увидеть реальные абсолютные пути, прежде чем что-то удалять или перемещать. Это тот же принцип «сначала покажи план, потом выполняй», который применяется в миграциях БД и деплой-скриптах: возможность безопасно посмотреть, что произойдёт, без реального изменения состояния — признак зрелого инструмента, а не только учебного скрипта. Отдельно стоит отметить glob('*.py') против rglob('**/*.py'): первый ищет только в текущей папке, второй — рекурсивно во всех вложенных, и путаница между ними — частая причина «скрипт ничего не находит», хотя нужные файлы явно есть где-то в дереве проекта.

                                                              Читать:

                                                              • pathlib
                                                              • @@ -277,14 +292,17 @@

                                                                Ловушки


                                                                День 111 (Сб): regex и обработка текстовых логов

                                                                -

                                                                Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                +

                                                                Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                Связь с проектом: шаг к CLI Task Manager

                                                                Теория

                                                                Регулярные выражения — мини-язык поиска по тексту. Модуль re: match — с начала строки, search — везде, findall — все совпадения, sub — замена. Raw-строки r"\d+" — backslash не экранируется Python. Группы () и именованные (?P<name>...) извлекают поля из лога.

                                                                Построчное чтение большого файла — O(1) память на строку; не загружай гигабайтный лог в read(). re.compile(pattern) переиспользуй в цикле — быстрее, чем компилировать каждый раз. regex101.com — тестируй паттерн до вставки в код.

                                                                Парсер server.log с named groups для timestamp, level, message — типичная задача DevOps/junior backend. Топ ERROR по часам — агрегация в dict. Замена IP на [REDACTED]re.sub. Жадный .* может «съесть» лишнее — будь осторожен с квантификаторами.

                                                                +

                                                                Ментальная модель: регулярное выражение — это мини-язык программирования, компилируемый в конечный автомат (finite state machine), который «читает» строку символ за символом и решает, продолжать совпадение или откатиться назад. Понимание этого объясняет и жадность квантификаторов (.* пытается захватить максимум, потом «отдаёт» посимвольно, если весь паттерн не совпал), и почему сложные вложенные квантификаторы могут вызывать катастрофический backtracking — экспоненциальное замедление на определённых входах.

                                                                +

                                                                Разбор логов — не учебная задача ради задачи: это одна из самых частых обязанностей junior/DevOps-инженера в первые месяцы работы, а извлечение структурированных полей через named groups — тот же навык, что валидация формата email или телефона регулярным выражением внутри Pydantic (неделя 18) или Zod (неделя 19), которые используют regex под капотом для паттернов вроде pattern=r'^\+?\d{10,15}$'.

                                                                +

                                                                Частое заблуждение — использовать regex там, где нужен полноценный парсер: для вложенных структур вроде HTML или JSON регулярка либо не справится, либо станет нечитаемым нагромождением экранирования — для таких форматов есть специализированные библиотеки. Другая типичная ошибка — забыть про re.search в пользу re.match, который проверяет совпадение только с начала строки, из-за чего кажется, что «регулярка не работает», хотя она просто ищет не там. В практике дня это прямо в критериях: парсинг должен быть построчным (generator, не read() целиком) — тот же принцип экономии памяти, что и в generator'ах дня 108. Именованные группы (?P<timestamp>...) вместо позиционных (...) — не просто удобство: они делают код устойчивым к изменению порядка групп в паттерне и превращают match.groupdict() в готовый словарь с понятными ключами вместо match.group(1), match.group(2), где легко перепутать индексы.

                                                                Читать:

                                                                • re module
                                                                • @@ -315,7 +333,7 @@

                                                                  Практика (лайт / MVP)

                                                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                  Если застрял

                                                                  -

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

                                                                  +

                                                                  Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                  Git

                                                                  • Закоммить изменения дня: git add week-16/git commit -m "week 16 day 111: log parser with regex"
                                                                  • @@ -328,14 +346,17 @@

                                                                    Ловушки


                                                                    День 112 (Вс): Ревью ООП и алгоритмов

                                                                    -

                                                                    Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                    -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                    +

                                                                    Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                    +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                    Связь с проектом: шаг к CLI Task Manager

                                                                    Теория

                                                                    Ревью ООП и алгоритмов готовит к SQLite-проекту недели. SOLID на junior-уровне: Single Responsibility — один класс, одна причина для изменения; Open/Closed — расширяй через композицию, не правь базовый класс везде. Не усложняй: простой скрипт — функции + dataclasses, сложный домен — классы с поведением.

                                                                    Code smells: god class на 500 строк, дублирование, magic numbers без констант. LeetCode Easy (Two Sum, Valid Parentheses) закрепляет структуры данных вне pet-проекта. Рефакторинг Expense Tracker на Expense + ExpenseStore — мост к TaskRepository.

                                                                    Подготовь venv для недели 17 с psycopg2-binary и python-dotenv. Конспект Big O на одну страницу — пригодится при EXPLAIN и выборе индексов. Тег week-16-done на финальном коммите.

                                                                    +

                                                                    Ментальная модель для ревью-дня: думай о SOLID не как о наборе догм, а как о наборе вопросов-фильтров, которые ты задаёшь коду после того, как он заработал, а не до. «У этого класса одна причина для изменения?» — если нет, скорее всего пора разделить god class на несколько с чёткой ответственностью. Это защита от переусложнения не меньше, чем от недоусложнения: простому CLI-скрипту не нужна абстрактная фабрика, а TaskRepository с несколькими бэкендами хранения — вполне.

                                                                    +

                                                                    Почему это важно дальше: рефакторинг Expense Tracker на Expense + ExpenseStore сегодня — прямая репетиция архитектуры, которую ты повторишь через два дня в SQLite-проекте недели, а затем в разделении models/schemas/crud FastAPI (неделя 18) и routes/controllers/services Express (неделя 19). Умение распознать «этот код стоит разбить на несколько сущностей» — переносимый навык, не привязанный к конкретному фреймворку.

                                                                    +

                                                                    Частое заблуждение выпускников этого этапа — считать, что больше классов и паттернов автоматически означает более «профессиональный» код; на практике over-engineering (фабрики фабрик для трёх типов объектов) так же вреден, как один файл на 500 строк. LeetCode Easy задачи в практике дня не про запоминание решений, а про распознавание паттернов (хеш-таблица вместо вложенного цикла, два указателя вместо перебора) — тот же навык, что пригодится при выборе структуры данных в реальном проекте, а не абстрактная гимнастика для собеседований. Ревью недели — это ещё и точка перехода: SQLite и sqlite3, с которыми ты работал в проекте, следующая неделя расширит до PostgreSQL и psycopg2, а ООП-приёмы (dataclass, ABC, композиция) станут строительными блоками моделей SQLAlchemy.

                                                                    Читать:

                                                                    • LeetCode Easy
                                                                    • @@ -366,7 +387,7 @@

                                                                      Практика (лайт / MVP)

                                                                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                      Если застрял

                                                                      -

                                                                      Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                      +

                                                                      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                      Git

                                                                      • Закоммить изменения дня: git add week-16/git commit -m "week 16 day 112: OOP review and LeetCode"
                                                                      • diff --git a/docs/w/17.html b/docs/w/17.html index 663009a..56cf320 100644 --- a/docs/w/17.html +++ b/docs/w/17.html @@ -22,14 +22,17 @@

                                                                        День 113 (Пн): SQL основы — SELECT, фильтрация, сортировка

                                                                        -

                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                        -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                        +

                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                        +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                        Связь с проектом: шаг к Library Database

                                                                        Теория

                                                                        SQL — декларативный язык: ты описываешь, какие данные нужны, а СУБД решает, как их достать. Базовый pipeline: SELECT колонки FROM таблицы WHERE условие ORDER BY сортировка LIMIT ограничение. DISTINCT убирает дубликаты строк в результате.

                                                                        Операторы фильтрации: =, <>, IN (...), BETWEEN, LIKE 'Py%' (префикс), IS NULL / IS NOT NULL. Агрегаты COUNT, SUM, AVG, MIN, MAX сворачивают множество строк. GROUP BY группирует перед агрегацией; HAVING фильтрует группы после агрегации — не путай с WHERE, который фильтрует строки до.

                                                                        Порядок выполнения SQL: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT. Понимание этого порядка объясняет, почему нельзя использовать алиас SELECT в WHERE той же фазы. SELECT * удобно в учебе, в production выбирай нужные колонки.

                                                                        +

                                                                        Ментальная модель: SQL декларативен, как заказ в ресторане — ты говоришь официанту «стейк средней прожарки», а не диктуешь повару пошаговый рецепт с температурой сковороды. СУБД (query planner) сама решает, каким путём достать данные — через полный перебор или индекс, в каком порядке соединить таблицы. Именно поэтому один и тот же SQL-запрос может выполняться по-разному в зависимости от статистики таблиц, а твоя задача — описать что нужно, а не как это получить.

                                                                        +

                                                                        Это станет фундаментом всего backend: когда через две недели ты напишешь select(Book).where(Book.title.ilike('%python%')) в SQLAlchemy, под капотом сгенерируется ровно такой же SELECT ... WHERE ... ILIKE, который ты пишешь сегодня руками. Без понимания сырого SQL отладка «странного» ORM-запроса превращается в гадание, а с ним — в чтение сгенерированного SQL и логичный вывод, почему он медленный или неверный.

                                                                        +

                                                                        Частое заблуждение — пытаться отфильтровать результат агрегации через WHERE: WHERE COUNT(*) > 2 вызовет ошибку, потому что на момент выполнения WHERE агрегаты ещё не посчитаны — для этого существует HAVING, которая работает уже после GROUP BY. Вторая типичная ошибка начинающих — забыть, что колонка, добавленная в SELECT без агрегатной функции, должна присутствовать и в GROUP BY, иначе строгий SQL-режим (в PostgreSQL это стандартное поведение) выдаст ошибку «column must appear in GROUP BY clause». Практика дня с HAVING count(*) > 2 — это ровно тренировка на понимание порядка выполнения, а не запоминание синтаксиса.

                                                                        Читать:

                                                                        • SQLBolt Lessons 1–6
                                                                        • @@ -73,14 +76,17 @@

                                                                          Ловушки


                                                                          День 114 (Вт): JOIN, INSERT, UPDATE, DELETE

                                                                          -

                                                                          Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                          -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                          +

                                                                          Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                          +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                          Связь с проектом: шаг к Library Database

                                                                          Теория

                                                                          Реляционная модель связывает таблицы ключами. INNER JOIN возвращает только строки с совпадением в обеих таблицах. LEFT JOIN сохраняет все строки «слева» и подставляет NULL справа, если совпадения нет — идеально для «клиенты без заказов» (WHERE orders.id IS NULL).

                                                                          DML — изменение данных: INSERT, UPDATE, DELETE. Золотое правило: UPDATE и DELETE всегда с осмысленным WHERE. Без WHERE ты изменишь или удалишь всю таблицу — катастрофа, даже в учебной БД. FOREIGN KEY и REFERENCES обеспечивают целостность на уровне СУБД, не только приложения.

                                                                          ON DELETE CASCADE удаляет дочерние записи вместе с родителем; SET NULL обнуляет FK. Транзакция BEGIN → операции → COMMIT или ROLLBACK — атомарность: либо всё, либо ничего. Забытый ON в JOIN даёт декартово произведение — взрыв числа строк.

                                                                          +

                                                                          Ментальная модель для JOIN — диаграмма Венна из двух пересекающихся кругов. INNER JOIN — это только пересечение (строки, у которых есть пара в обеих таблицах); LEFT JOIN — весь левый круг целиком плюс то, что попало в пересечение, а недостающая часть справа заполняется NULL. Именно поэтому «клиенты без заказов» находятся через LEFT JOIN ... WHERE orders.id IS NULL: NULL в правой части и есть признак отсутствия совпадения.

                                                                          +

                                                                          Это фундамент, который прорастёт в обе следующие недели: relationship() в SQLAlchemy (неделя 18) под капотом генерирует ровно такой же JOIN, когда ты обращаешься к author.books, а понимание ON DELETE CASCADE, которое ты настраиваешь сегодня, определяет, будут ли реальные пользовательские данные корректно удаляться или зависать сиротами при удалении родительской записи в продакшене.

                                                                          +

                                                                          Частое и самое опасное заблуждение — думать, что DELETE FROM orders WHERE customer_id = 5 «удалит только пять заказов», забыв, что без WHERE DELETE FROM orders стирает все строки таблицы безвозвратно, и в отличие от файла это не попадёт в корзину. Именно поэтому в критериях дня явно требуется тестировать деструктивные операции через BEGIN + ROLLBACK, прежде чем выполнять их «по-настоящему»: привычка проверять запрос в транзакции с откатом — это тот самый навык, который убережёт от инцидента на реальной базе данных. Такая же осторожность нужна и с самим JOIN: забытое условие ON превращает соединение в декартово произведение, где каждая строка левой таблицы умножается на каждую строку правой — на таблицах в тысячи строк результат может незаметно взорваться до миллионов, съедая память и время.

                                                                          Читать:

                                                                          • SQLBolt — JOINs
                                                                          • @@ -111,7 +117,7 @@

                                                                            Практика (лайт / MVP)

                                                                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                            Если застрял

                                                                            -

                                                                            Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                            +

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

                                                                            Git

                                                                            • Закоммить изменения дня: git add week-17/git commit -m "week 17 day 114: JOINs and DML with transactions"
                                                                            • @@ -124,14 +130,17 @@

                                                                              Ловушки


                                                                              День 115 (Ср): Нормализация и проектирование схемы

                                                                              -

                                                                              Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                              -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                              +

                                                                              Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                              +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                              Связь с проектом: шаг к Library Database

                                                                              Теория

                                                                              Нормализация убирает избыточность и аномалии обновления. 1NF — атомарные значения в ячейке (не CSV списка id). 2NF — нет частичных зависимостей от составного ключа. 3NF — нет транзитивных зависимостей (город заёмщика не должен дублироваться в каждой записи loan, если borrower уже хранит город).

                                                                              One-to-many: FK в таблице «многих» (books.author_id → authors.id). Many-to-many: junction table (task_tags с двумя FK). Именование: snake_case, plural tables (authors, books) — выбери конвенцию и держись её. CHECK (price > 0) и NOT NULL валидируют на уровне БД.

                                                                              Денормализация — осознанный trade-off ради скорости чтения, не лень проектировать. ER-диаграмма на dbdiagram.io или Mermaid фиксирует связи до написания SQL. Антипаттерн: хранить список id в одной TEXT-колонке.

                                                                              +

                                                                              Ментальная модель нормализации — аккуратная картотека, где каждый факт хранится ровно в одном месте. Если город заёмщика продублирован в каждой записи loan, изменение города потребует найти и поправить десятки строк, а забытая хотя бы одна — уже аномалия обновления (данные противоречат друг другу). Нормализованная схема устраняет саму возможность такого рассинхрона: город хранится один раз в borrowers, и loans лишь ссылается на него по FK.

                                                                              +

                                                                              Схема «Библиотека», которую ты проектируешь сегодня, — не разовое упражнение: это буквально та же схема authors/books/borrowers/loans, которую ты перенесёшь в SQLAlchemy-модели на неделе 18 и в schema.sql для Express на неделе 19. Ошибка в проектировании здесь (например, отсутствие junction table для many-to-many) аукнется трижды — придётся переделывать модели во всех трёх проектах.

                                                                              +

                                                                              Частое заблуждение — доводить нормализацию до абсурда, разбивая всё на мельчайшие таблицы там, где осознанная денормализация была бы разумным компромиссом ради скорости чтения (это решение, а не лень). Куда более частая ошибка новичков — обратная: хранить список связанных id одной строкой через запятую в TEXT-колонке вместо junction table, что делает невозможными нормальные JOIN-запросы и проверку целостности через FK. В практике дня это прямо проверяется: если книге нужно несколько жанров, единственный правильный путь — таблица book_genres с двумя внешними ключами, а не текстовое поле. Отдельно стоит проговорить конвенции именования: snake_case, множественное число для таблиц (authors, а не author) — мелочь, которая экономит часы споров в команде и делает схему предсказуемой для любого, кто открывает её впервые.

                                                                              Читать:

                                                                              • PostgreSQL Tutorial — Getting Started
                                                                              • @@ -162,7 +171,7 @@

                                                                                Практика (лайт / MVP)

                                                                                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                Если застрял

                                                                                -

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

                                                                                +

                                                                                Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                Git

                                                                                • Закоммить изменения дня: git add week-17/git commit -m "week 17 day 115: library schema and ER diagram"
                                                                                • @@ -175,14 +184,17 @@

                                                                                  Ловушки


                                                                                  День 116 (Чт): PostgreSQL — установка и отличия от SQLite

                                                                                  -

                                                                                  Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                  -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                  +

                                                                                  Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                  +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                  Связь с проектом: шаг к Library Database

                                                                                  Теория

                                                                                  PostgreSQL — серверная СУБД для production: concurrent access, роли, extensions, богатые типы (JSONB, UUID, TIMESTAMPTZ). SQLite — один файл, zero-config, идеален для прототипов и встроенных приложений. На этой неделе ты переносишь схему «Библиотека» из SQLite в PG.

                                                                                  -

                                                                                  Docker: docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=pass postgres:16 поднимает изолированный инстанс за секунды. Клиенты: psql, pgAdmin, DBeaver. Диалектные отличия: AUTOINCREMENT (SQLite) vs SERIAL / GENERATED ALWAYS AS IDENTITY (PostgreSQL).

                                                                                  +

                                                                                  Docker: docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=pass postgres:16 поднимает изолированный инстанс за секунды. Клиенты: psql, pgAdmin, DBeaver — psql быстрее для точечных запросов и скриптов, GUI-клиенты удобнее для визуального просмотра схемы. Диалектные отличия: AUTOINCREMENT (SQLite) vs SERIAL / GENERATED ALWAYS AS IDENTITY (PostgreSQL).

                                                                                  DATABASE_URL=postgresql://user:pass@localhost:5432/library — стандартная строка подключения для приложений. Документируй пароль в .env.example без реальных значений. Сравни SQLite vs PG письменно: когда файл достаточен, когда нужен сервер.

                                                                                  +

                                                                                  Ментальная модель: SQLite — это личный блокнот-файл, лежащий рядом с программой (embedded, без сети, один процесс пишет за раз); PostgreSQL — это офисный сервер базы данных, к которому по сети одновременно подключаются десятки клиентов через клиент-серверный протокол. Отсюда и разница use case: прототип, CLI-утилита, мобильное приложение — SQLite; веб-сервис с конкурентным доступом — PostgreSQL.

                                                                                  +

                                                                                  Эта миграция — не разовое упражнение: практически каждый проект, который ты соберёшь дальше в программе (FastAPI на неделе 18, Express на неделе 19, деплой на неделе 21), будет подключаться именно к PostgreSQL через одну и ту же переменную DATABASE_URL — сегодняшняя настройка Docker-контейнера и строки подключения используется без изменений ещё как минимум трижды.

                                                                                  +

                                                                                  Частое заблуждение — считать SQL PostgreSQL и SQLite полностью взаимозаменяемым диалектом: AUTOINCREMENT в SQLite становится SERIAL или GENERATED ALWAYS AS IDENTITY в PostgreSQL, типы данных богаче (JSONB, UUID, TIMESTAMPTZ не имеют прямых аналогов в SQLite), а поведение constraint-ов местами строже. В практике дня перенос схемы «Библиотека» специально выявляет эти расхождения — их стоит зафиксировать письменно в notes/pg-vs-sqlite.md, чтобы не наступать на те же грабли в будущих проектах. Ещё один момент, который легко упустить: SQLite не требует отдельного процесса-сервера и пароля, а PostgreSQL требует явного управления доступом (роли, пароли, сетевые порты) — именно поэтому сегодняшняя настройка .env.example с DATABASE_URL без реальных секретов в самом репозитории становится обязательной привычкой на все оставшиеся недели курса. Полезно письменно зафиксировать и обратное: в каких случаях SQLite достаточно даже для боевого использования — например, мобильные и десктопные приложения, локальные кэши или сервисы с одним писателем и низкой конкурентной нагрузкой, где сетевой сервер был бы избыточен.

                                                                                  Читать:

                                                                                  • PostgreSQL Downloads
                                                                                  • @@ -213,7 +225,7 @@

                                                                                    Практика (лайт / MVP)

                                                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                    Если застрял

                                                                                    -

                                                                                    Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                    +

                                                                                    Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                    Git

                                                                                    • Закоммить изменения дня: git add week-17/git commit -m "week 17 day 116: PostgreSQL setup and schema migration"
                                                                                    • @@ -226,14 +238,17 @@

                                                                                      Ловушки


                                                                                      День 117 (Пт): Индексы и EXPLAIN ANALYZE

                                                                                      -

                                                                                      Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                      -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                      +

                                                                                      Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                      +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                      Связь с проектом: шаг к Library Database

                                                                                      Теория

                                                                                      Индекс — структура данных (обычно B-tree), ускоряющая поиск по колонке ценой замедления INSERT/UPDATE. CREATE INDEX idx_books_title ON books(title) помогает WHERE title = '...' и LIKE 'Python%' (префикс), но не LIKE '%python' (leading wildcard).

                                                                                      EXPLAIN ANALYZE показывает реальный план выполнения: Seq Scan (полный перебор) vs Index Scan (по дереву). Сравни cost, rows, actual time до и после индекса на таблице с 10 000+ строк. Составной индекс (author_id, title) — порядок колонок важен для составных запросов.

                                                                                      Use The Index, Luke объясняет, когда индекс помогает, а когда оптимизатор его игнорирует. Индекс на каждую колонку — перебор: каждая запись обновляет все индексы. Документируй замеры в notes/indexes.md — это навык для собеседований.

                                                                                      +

                                                                                      Ментальная модель: индекс — это алфавитный указатель в конце книги. Без него, чтобы найти все упоминания слова, придётся пролистать каждую страницу (Seq Scan, O(n)); с указателем ты сразу открываешь нужную страницу (Index Scan, ближе к O(log n)) — та самая разница между линейным и логарифмическим ростом, которую ты изучал на неделе 16 в контексте Big O, здесь материализуется в конкретных миллисекундах.

                                                                                      +

                                                                                      Это — один из главных практических навыков backend-разработчика: медленный endpoint в проекте FastAPI (неделя 18) почти всегда диагностируется и чинится именно этим приёмом — EXPLAIN ANALYZE показывает, какой шаг запроса «съедает» время, а индекс на нужной колонке превращает Seq Scan в Index Scan. Собеседования на backend-позиции регулярно спрашивают именно про это: «как найти и ускорить медленный запрос».

                                                                                      +

                                                                                      Частое заблуждение — думать, что «индекс всегда ускоряет чтение, значит стоит поставить его на каждую колонку». На самом деле у индекса есть цена: каждая вставка, обновление или удаление строки должна обновить все индексы таблицы, что замедляет запись и увеличивает размер БД на диске. Кроме того, оптимизатор PostgreSQL может проигнорировать индекс на маленькой таблице или при низкой селективности колонки (например, поле status с тремя значениями на миллион строк), потому что полный перебор иногда дешевле навигации по дереву. Именно поэтому критерий практики требует не просто создать индекс, а сравнить EXPLAIN ANALYZE до и после цифрами, а не полагаться на интуицию.

                                                                                      Читать:

                                                                                      • PostgreSQL Indexes
                                                                                      • @@ -277,14 +292,17 @@

                                                                                        Ловушки


                                                                                        День 118 (Сб): SQLite/PostgreSQL из Python

                                                                                        -

                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                        -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                        +

                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                        +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                        Связь с проектом: шаг к Library Database

                                                                                        Теория

                                                                                        Приложение общается с БД через драйвер. Встроенный sqlite3 использует placeholders ?; psycopg2 / psycopg3 для PostgreSQL — %s. Никогда не вставляй пользовательский ввод в SQL через f-string — это SQL injection. Только параметризованные запросы: cursor.execute('SELECT * FROM books WHERE id = %s', (book_id,)).

                                                                                        Context manager with conn: коммитит при успехе и откатывает при исключении. DATABASE_URL из .env через python-dotenv — 12-factor config. Connection pool (в веб-приложении) переиспользует соединения под нагрузкой; в CLI достаточно одного подключения на операцию.

                                                                                        Абстракция репозитория с методами fetch_all, execute позволяет переключать SQLite и PostgreSQL флагом --db. Скрипт миграции sqlite → postgres учит переносу данных между СУБД. Забытый conn.commit() — изменения не сохранятся.

                                                                                        +

                                                                                        Ментальная модель: плейсхолдер (? или %s) — это форма с чётко заданными полями для заполнения, которую драйвер сначала отправляет в СУБД как шаблон, а данные передаёт отдельно как значения. СУБД никогда не интерпретирует значения как код — в отличие от f-строки, где пользовательский ввод буквально дописывается в текст SQL-запроса, и злоумышленник может вставить туда '; DROP TABLE users; -- вместо ожидаемого имени.

                                                                                        +

                                                                                        Абстракция репозитория, которую ты пишешь сегодня (fetch_all, execute с переключением --db), — не учебная условность: это прямой предшественник паттерна Repository/CRUD-слоя в SQLAlchemy на неделе 18 и Pool.query() в Express на неделе 19 — везде задача одна и та же: изолировать SQL от бизнес-логики и гарантировать безопасные параметризованные запросы.

                                                                                        +

                                                                                        Частое заблуждение — думать, что with conn: в психопг2 закрывает и само соединение: на самом деле контекстный менеджер отвечает только за транзакцию — коммитит при успешном выходе или откатывает при исключении, но соединение остаётся открытым и должно быть закрыто отдельно (conn.close() или отдельный with). Вторая типичная ошибка — забыть conn.commit() при работе без контекстного менеджера: запрос выполнится, SELECT после него в той же сессии покажет изменения, но после перезапуска приложения данные окажутся «потерянными», потому что физически не были записаны на диск. Полезная привычка на будущее: заворачивать операции записи в with conn: или явный try/except/finally с rollback() в случае ошибки — тот же паттерн, который через несколько дней превратится в session SQLAlchemy с автоматическим управлением транзакцией на уровне ORM.

                                                                                        Читать:

                                                                                        • sqlite3
                                                                                        • @@ -315,7 +333,7 @@

                                                                                          Практика (лайт / MVP)

                                                                                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                          Если застрял

                                                                                          -

                                                                                          Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                          +

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

                                                                                          Git

                                                                                          • Закоммить изменения дня: git add week-17/git commit -m "week 17 day 118: Python psycopg2 library CLI"
                                                                                          • @@ -328,14 +346,17 @@

                                                                                            Ловушки


                                                                                            День 119 (Вс): Ревью SQL и подготовка к ORM

                                                                                            -

                                                                                            Время (полный): ~25м теория · ~2.5ч практика · ~10м Git · ~40м ревью
                                                                                            -Время (лайт): ~15м теория · ~1ч практика (MVP) · ~10м Git
                                                                                            +

                                                                                            Время (полный): ~1ч теория · ~2.5ч практика · ~10м Git · ~40м ревью
                                                                                            +Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                            Связь с проектом: шаг к Library Database

                                                                                            Теория

                                                                                            Ревью SQL закрепляет фундамент перед ORM на неделе 18. ACID: Atomicity (всё или ничего), Consistency (инварианты БД), Isolation (параллельные транзакции не мешают), Durability (commit переживает сбой). Транзакции — не абстракция, а гарантия при переводе денег или выдаче книги.

                                                                                            Views — сохранённые запросы; stored procedures — логика внутри БД (обзор). Isolation levels (read committed, serializable) влияют на фантомные чтения — на junior достаточно знать, что они существуют. SQL Style Guide делает запросы читаемыми для команды.

                                                                                            ORM (SQLAlchemy) маппит таблицы на классы Python: меньше boilerplate SQL, но риск N+1 и «магических» запросов. Понимание raw SQL остаётся обязательным для отладки и оптимизации. Установи sqlalchemy fastapi uvicorn в venv — старт недели 18.

                                                                                            +

                                                                                            Ментальная модель ACID — это четыре независимых обещания, которые транзакция даёт тебе как разработчику, и их стоит держать в голове как чек-лист перед любой операцией с деньгами или запасами: Atomicity — операция либо выполнится целиком, либо не выполнится вовсе, без промежуточного «наполовину»; Consistency — база данных переходит из одного валидного состояния в другое, не нарушая constraints; Isolation — параллельные транзакции не видят «грязных» промежуточных изменений друг друга; Durability — после commit данные переживут даже сбой питания.

                                                                                            +

                                                                                            Это не абстракция ради экзамена: session.commit() / session.rollback() в SQLAlchemy (неделя 18) и pool.query('COMMIT') в Express (неделя 19) опираются ровно на эти же гарантии — ORM не отменяет необходимости понимать ACID, а лишь делает транзакционную границу менее заметной в коде, из-за чего баги «забыл закоммитить» или «два запроса пересеклись» стали чаще, а не реже.

                                                                                            +

                                                                                            Частое заблуждение выпускников этой недели — думать, что после перехода на ORM сырой SQL больше не понадобится. На практике чтение EXPLAIN-плана, отладка неожиданно медленного ORM-запроса или написание сложной агрегации, которую ORM выразить неудобно, — всё это требует свободного владения SQL, которое ты наработал за эту неделю. Финализация queries.sql с 15+ запросами в практике дня — это не формальность для проекта, а последняя проверка того, что фундамент действительно прочный перед тем, как он будет частично скрыт слоем абстракции. Views и stored procedures стоит знать хотя бы на уровне «это существует и для чего»: view — это именованный сохранённый запрос, который можно использовать как обычную таблицу для чтения, а stored procedure переносит часть логики внутрь самой СУБД — оба инструмента встречаются в legacy-системах, и способность их прочитать пригодится раньше, чем способность написать с нуля.

                                                                                            Читать:

                                                                                            • SQLBolt
                                                                                            • @@ -366,7 +387,7 @@

                                                                                              Практика (лайт / MVP)

                                                                                              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                              Если застрял

                                                                                              -

                                                                                              Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                              +

                                                                                              Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                              Git

                                                                                              • Закоммить изменения дня: git add week-17/git commit -m "week 17 day 119: SQL review and 15 queries"
                                                                                              • diff --git a/docs/w/18.html b/docs/w/18.html index c328e5b..fb2c931 100644 --- a/docs/w/18.html +++ b/docs/w/18.html @@ -22,14 +22,17 @@

                                                                                                День 120 (Пн): SQLAlchemy — модели и сессии

                                                                                                -

                                                                                                Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                +

                                                                                                Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                Связь с проектом: шаг к Library REST API

                                                                                                Теория

                                                                                                SQLAlchemy 2.0 — современный ORM для Python. DeclarativeBase, Mapped[type] и mapped_column() задают модели типобезопасно. Engine — подключение к PostgreSQL; SessionLocal — фабрика сессий. Сессия — unit of work: session.add(obj), commit(), refresh(obj) для актуализации из БД.

                                                                                                relationship() с back_populates связывает Author и Book двусторонне без ручных JOIN в каждом запросе. ORM model (Author в models/) — внутреннее представление; Pydantic schema (AuthorRead) — контракт API. Не смешивай их: утечёт password_hash в JSON.

                                                                                                get_db() generator с yield и finally: session.close() — паттерн для FastAPI. Alembic версионирует схему (обзор); на этой неделе достаточно create_all + seed. Забытый commit() — данные «исчезают» после перезапуска.

                                                                                                +

                                                                                                Ментальная модель: сессия SQLAlchemy — это «корзина покупок». Ты добавляешь и меняешь объекты (session.add(book), book.title = '...') — они лежат в корзине как черновик, видимый только тебе. Ничего не попадает на «склад» (в таблицы БД) до commit(); если передумал — rollback() выбрасывает всё содержимое корзины без следа. Это разделение «черновик в памяти» и «зафиксированное состояние в БД» — ключ к пониманию, почему объект может «казаться сохранённым» в текущем коде, но исчезнуть при следующем запуске программы.

                                                                                                +

                                                                                                Синтаксис моделей, который ты пишешь сегодня, — это не просто ORM-специфика: class Author(Base): id: Mapped[int] = mapped_column(primary_key=True) — прямое продолжение классов и type hints с недели 16, применённое к описанию таблиц. А паттерн get_db() с yield и закрытием сессии в finally — это заготовка для Dependency Injection, которую ты формализуешь через Depends() уже послезавтра, и она же концептуально повторится в Node.js как «одно соединение из пула на один запрос» на неделе 19.

                                                                                                +

                                                                                                Частое заблуждение — считать ORM-модель (Author из models/) и Pydantic-схему (AuthorRead для API) одной и той же сущностью, которую можно возвращать из эндпоинта напрямую. Это разные слои с разными целями: ORM-модель отражает структуру таблицы и может содержать чувствительные или внутренние поля (password_hash, internal_notes), а API-схема — это явно объявленный публичный контракт. Смешение слоёв — прямой путь к утечке данных в JSON-ответе. Вторая типичная ошибка — забыть session.commit(), из-за чего изменения видны в рамках текущего процесса (SQLAlchemy их закэшировал), но исчезают после перезапуска сервера, потому что физически не записаны в PostgreSQL.

                                                                                                Читать:

                                                                                                • SQLAlchemy 2.0 Quickstart
                                                                                                • @@ -73,14 +76,17 @@

                                                                                                  Ловушки


                                                                                                  День 121 (Вт): CRUD через ORM и запросы

                                                                                                  -

                                                                                                  Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                  -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                  +

                                                                                                  Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                  +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                  Связь с проектом: шаг к Library REST API

                                                                                                  Теория

                                                                                                  CRUD через ORM использует SQLAlchemy 2.0 style select(), не legacy session.query(). session.get(Model, id) — lookup по primary key с identity map cache. session.scalars(select(Book).where(...)).all() возвращает список ORM-объектов. Фильтры: .where(), .join(), .order_by(), .limit(), .offset() для пагинации.

                                                                                                  N+1 problem: цикл по авторам + author.books внутри генерирует запрос на каждую итерацию. Решение — eager loading: selectinload(Author.books) или joinedload. Замерь количество SQL-запросов до и после — наглядный урок.

                                                                                                  session.delete(obj) + commit() удаляет с учётом cascade rules. Пагинация page=1, size=20 — обязательна для API endpoints. Вынеси CRUD в crud/authors.py — routes остаются тонкими. title.ilike('%python%') — case-insensitive поиск в PostgreSQL.

                                                                                                  +

                                                                                                  Ментальная модель N+1: представь, что нужно доставить книги 20 авторов, но вместо одной фуры, которая привозит всё за один рейс (selectinload — один дополнительный запрос со списком id), курьер каждый раз едет на склад за книгами одного конкретного автора — 20 отдельных поездок. Каждое обращение к author.books внутри цикла без eager loading — это отдельный SQL-запрос к базе, и для 100 авторов это будет 101 запрос вместо 2.

                                                                                                  +

                                                                                                  N+1 — не теоретическая проблема из учебника: это самая частая жалоба на производительность в production API, построенных на ORM, и именно её ты научишься видеть и чинить сегодня. В любом реальном проекте на SQLAlchemy, который ты соберёшь после курса, первый вопрос при жалобе «эндпоинт тормозит» — это «сколько SQL-запросов он генерирует», и умение включить логирование запросов и посчитать их — прямой навык из сегодняшней практики.

                                                                                                  +

                                                                                                  Частое заблуждение — думать, что раз session.query() (SQLAlchemy 1.x) всё ещё работает и встречается в старых туториалах, значит это актуальный способ писать запросы. Однако 2.0-style select() — новый стандарт с лучшей типизацией и явным поведением, и весь код недели построен на нём. Вторая ошибка — включать eager loading (selectinload) на все связи по умолчанию «на всякий случай»: это не бесплатно, каждая дополнительная связь — дополнительный запрос или JOIN, поэтому выбор между selectinload и joinedload должен опираться на реальный паттерн использования, а не привычку. Практическая привычка на будущее: при любом подозрении на медленный endpoint включай логирование SQL (echo=True в engine) и считай запросы за один HTTP-вызов — это тот же диагностический рефлекс, что и EXPLAIN ANALYZE на прошлой неделе, только применённый к ORM-коду.

                                                                                                  Читать:

                                                                                                  • SQLAlchemy Select
                                                                                                  • @@ -111,7 +117,7 @@

                                                                                                    Практика (лайт / MVP)

                                                                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                    Если застрял

                                                                                                    -

                                                                                                    Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                    +

                                                                                                    Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                    Git

                                                                                                    • Закоммить изменения дня: git add week-18/git commit -m "week 18 day 121: ORM CRUD and N+1 fix"
                                                                                                    • @@ -124,14 +130,17 @@

                                                                                                      Ловушки


                                                                                                      День 122 (Ср): FastAPI — первый API

                                                                                                      -

                                                                                                      Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                      -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                      +

                                                                                                      Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                      +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                      Связь с проектом: шаг к Library REST API

                                                                                                      Теория

                                                                                                      FastAPI — ASGI-фреймворк с автоматической валидацией из type hints. Path params (/notes/{id}), query params (?skip=0), request body (Pydantic model) — три входа данных. Pydantic проверяет типы в runtime и генерирует OpenAPI schema для Swagger.

                                                                                                      uvicorn main:app --reload — dev-сервер с hot reload. /docs (Swagger UI) и /redoc — бесплатная интерактивная документация. response_model=NoteRead отсекает внутренние поля ORM от публичного JSON. Невалидный body → 422 Unprocessable Entity с деталями ошибок.

                                                                                                      Начни с in-memory CRUD для Note — отдели изучение FastAPI от SQLAlchemy. NoteCreate, NoteRead, NoteUpdate (optional fields) — три схемы для разных операций. Mutable default в Pydantic: Field(default_factory=list), не tags=[].

                                                                                                      +

                                                                                                      Ментальная модель FastAPI — «contract-first без отдельного контракта»: обычно документацию API пишут отдельно от кода, и она рассинхронизируется через месяц. Здесь type hints и Pydantic-модель — это и есть контракт: FastAPI читает их один раз при старте и генерирует из них одновременно валидацию, сериализацию и Swagger-документацию. Написал title: str — и невалидный запрос без title автоматически получит 422 с понятным объяснением, без единой строчки ручной проверки.

                                                                                                      +

                                                                                                      Почему это выходит за рамки одного дня: дисциплина response_model, которую ты закладываешь здесь на игрушечном Note, — это тот самый механизм, который через два дня не даст утечь внутренним полям ORM-модели (password_hash, internal_id) в публичный JSON API «Библиотеки». А привычка объявлять отдельные схемы для создания, чтения и обновления (NoteCreate без id, NoteRead с id, NoteUpdate с опциональными полями) — стандартный паттерн, который ты повторишь для Author, Book, Loan уже завтра.

                                                                                                      +

                                                                                                      Частое заблуждение — думать, что раз Pydantic валидирует типы, значит любые дефолтные значения безопасны, включая tags: list[str] = []. В чистом Python mutable default-аргумент функции действительно опасен — он создаётся один раз и разделяется между вызовами; Pydantic обрабатывает этот случай корректно сам, но Field(default_factory=list) — явный, самодокументируемый способ показать намерение и защититься от этой более общей проблемы Python, если она встретится вне Pydantic. Вторая ошибка новичков — возвращать ORM- или dict-объект напрямую без response_model, из-за чего в ответе оказываются лишние или чувствительные поля, которые никто не собирался показывать наружу. /docs и /redoc при этом не два независимых артефакта, а два разных представления одной и той же OpenAPI-схемы — Swagger удобен для ручного тестирования прямо из браузера, ReDoc — для чтения документации как справочника.

                                                                                                      Читать:

                                                                                                      • FastAPI First Steps
                                                                                                      • @@ -162,7 +171,7 @@

                                                                                                        Практика (лайт / MVP)

                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                        Если застрял

                                                                                                        -

                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                        +

                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                        Git

                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m "week 18 day 122: FastAPI in-memory notes API"
                                                                                                        • @@ -175,14 +184,17 @@

                                                                                                          Ловушки


                                                                                                          День 123 (Чт): Dependency Injection и подключение БД

                                                                                                          -

                                                                                                          Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                          -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                          +

                                                                                                          Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                          +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                          Связь с проектом: шаг к Library REST API

                                                                                                          Теория

                                                                                                          Dependency Injection в FastAPI — через Depends. get_db() с yield создаёт сессию на один request и закрывает в finally — не используй глобальную session (race conditions). Depends(get_db) в параметрах endpoint автоматически резолвит зависимость.

                                                                                                          HTTPException(status_code=404, detail="Author not found") — контролируемые ошибки вместо 500. Семантика статусов: 200 OK, 201 Created, 204 No Content, 404 Not Found, 409 Conflict, 422 Validation Error. Вложенные dependencies (get_current_user на нед. 20) строят цепочку проверок.

                                                                                                          Pydantic schemas AuthorCreate / AuthorRead отделяют вход и выход. Nested resource GET /authors/{id}/books — RESTful вложенность. Lifespan events (startup/shutdown) — для инициализации пула и закрытия соединений (обзор).

                                                                                                          +

                                                                                                          Ментальная модель Depends() — вендинговый автомат: ты не заботишься, как приготовлен кофе, ты просто объявляешь «мне нужна сессия БД» в параметрах функции-эндпоинта, а FastAPI сам вызывает get_db(), отдаёт тебе готовую сессию и гарантированно закрывает её после ответа — даже если внутри эндпоинта произошло исключение. Ты декларируешь зависимость, а не управляешь её жизненным циклом руками.

                                                                                                          +

                                                                                                          Это не разовый трюк для сегодняшнего дня: ровно тот же механизм Depends станет способом получить текущего аутентифицированного пользователя (get_current_user) на неделе 20 — сегодняшний Depends(get_db) это буквально тренировочная версия завтрашней цепочки проверок доступа. Понимание, что зависимости можно комбинировать и они выполняются перед телом эндпоинта, снимает половину вопросов про то, «как вообще работает auth» позже.

                                                                                                          +

                                                                                                          Частое заблуждение — считать, что одна глобальная сессия на всё приложение (созданная один раз при старте) — безобидная оптимизация, которая экономит ресурсы. На самом деле под конкурентной нагрузкой это прямой путь к состоянию гонки: два одновременных запроса начнут писать в одну и ту же сессию, и данные одного пользователя могут утечь в ответ другому или вызвать неконсистентные commit. Вторая ошибка — возвращать 200 OK при удалении несуществующего ресурса вместо честного 404 через HTTPException: API должен явно сообщать о промахе, а не молча делать вид, что всё прошло успешно. Nested resource GET /authors/{id}/books заслуживает отдельного внимания: это не отдельная таблица, а тот же relationship, показанный под другим URL — RESTful вложенность выражает связь между ресурсами через структуру пути, а не через отдельный, никак не связанный endpoint.

                                                                                                          Читать:

                                                                                                          • FastAPI Dependencies
                                                                                                          • @@ -213,7 +225,7 @@

                                                                                                            Практика (лайт / MVP)

                                                                                                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                            Если застрял

                                                                                                            -

                                                                                                            Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                            +

                                                                                                            Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                            Git

                                                                                                            • Закоммить изменения дня: git add week-18/git commit -m "week 18 day 123: FastAPI DI and authors endpoints"
                                                                                                            • @@ -226,14 +238,17 @@

                                                                                                              Ловушки


                                                                                                              День 124 (Пт): Полный REST API «Библиотека»

                                                                                                              -

                                                                                                              Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                              -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                              +

                                                                                                              Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                              +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                              Связь с проектом: шаг к Library REST API

                                                                                                              Теория

                                                                                                              REST — соглашения, не протокол. URL — существительные (/books), HTTP verbs — действия (GET читать, POST создать, PUT/PATCH обновить, DELETE удалить). GET, PUT, DELETE идемпотентны: повторный запрос даёт тот же эффект. POST — нет (каждый создаёт новый ресурс).

                                                                                                              APIRouter модульно группирует endpoints: routers/authors.py, prefix /api/v1, tags для Swagger. Пагинация в едином формате: { items, total, page, size }. Фильтрация через query: ?status=active&search=python. Версионирование /api/v1 защищает фронтенд от breaking changes.

                                                                                                              Бизнес-правила в API: нельзя выдать уже выданную книгу → 409 Conflict, не 500. Глаголы в URL (/getAuthors) — антипаттерн. Отсутствие валидации FK — 500 вместо понятного 404.

                                                                                                              +

                                                                                                              Ментальная модель REST: URL — это витрина магазина с существительными на ценниках (/books, /authors), а HTTP-глагол — это то, что ты делаешь с товаром на этой витрине (посмотреть — GET, положить в корзину — POST, поменять — PUT/PATCH, убрать — DELETE). Действие никогда не должно быть зашито в само название полки; если тянет написать /getBooks или /createAuthor, это сигнал, что мышление соскользнуло с ресурсов на процедуры.

                                                                                                              +

                                                                                                              Структура routers/authors.py, books.py, loans.py с общим префиксом /api/v1, которую ты собираешь сегодня, — прямой аналог того, что ты построишь в Express на неделе 19 через routes/, controllers/, services/: разные языки, одна и та же архитектурная идея модульного разделения по ресурсам. Сравнение этих двух реализаций в конце месяца станет наглядным доказательством, что архитектурное мышление важнее конкретного фреймворка.

                                                                                                              +

                                                                                                              Частое заблуждение — трактовать любое нарушение бизнес-правила (книга уже выдана, лимит займов исчерпан) как ошибку сервера и возвращать 500. На деле это ожидаемая, предсказуемая ситуация в доменной логике, и правильный ответ — 409 Conflict с понятным сообщением, которое фронтенд может показать пользователю осмысленно. Вторая распространённая ошибка — не проверять существование внешнего ключа перед вставкой (например, author_id, которого нет), из-за чего клиент получает малопонятную 500-ю ошибку от БД вместо контролируемого 404 или 400 от приложения. Версионирование через префикс /api/v1 — ещё одна деталь, которую легко недооценить: она защищает уже подключившийся фронтенд от breaking changes, когда через несколько месяцев понадобится изменить форму ответа — старые клиенты продолжат работать с /api/v1, пока новые постепенно переходят на /api/v2.

                                                                                                              Читать:

                                                                                                              • FastAPI Bigger Applications
                                                                                                              • @@ -277,14 +292,17 @@

                                                                                                                Ловушки


                                                                                                                День 125 (Сб): Тестирование API и обработка ошибок

                                                                                                                -

                                                                                                                Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                +

                                                                                                                Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                Связь с проектом: шаг к Library REST API

                                                                                                                Теория

                                                                                                                Тестирование API — страховка от регрессий. FastAPI TestClient (на базе httpx) шлёт запросы без реального сетевого сервера. pytest fixtures в conftest.py: client, db session, sample data. Test DB — отдельная schema или SQLite in-memory; никогда production.

                                                                                                                Arrange-Act-Assert: подготовь данные, выполни запрос, проверь status и body. Тесты: create author 201, get missing 404, loan conflict 409. pytest -v --tb=short — читаемый вывод. Rollback после каждого теста — иначе flaky tests.

                                                                                                                Global exception handlers: IntegrityError → 409, generic → 500 без stack trace в production. CORS middleware понадобится на нед. 21. Coverage pytest --cov=app показывает пробелы. ≥ 8 тестов — минимум для уверенности в CRUD и ошибках.

                                                                                                                +

                                                                                                                Ментальная модель TestClient — «робот-клиент», который стучится в твоё FastAPI-приложение напрямую в памяти, без реального TCP-сокета и сетевого стека. Отсюда и скорость (сотни тестов выполняются за секунды), и детерминированность (нет случайных сетевых задержек или занятых портов) — тесты можно гонять на каждый коммит без страха, что они станут узким местом разработки.

                                                                                                                +

                                                                                                                Автотесты — это не формальность для галочки в критериях: именно они дают возможность бесстрашно рефакторить код проекта недели, зная, что любая регрессия будет поймана до того, как попадёт в продакшен. Это тот же навык и тот же паттерн Arrange-Act-Assert, который ты используешь на любой позиции разработчика, независимо от языка — pytest здесь, Jest/Vitest в Node-мире.

                                                                                                                +

                                                                                                                Частое заблуждение — писать тесты только на happy path («создание автора работает») и считать это достаточным покрытием. В реальности большинство продакшен-багов живёт именно в граничных случаях: что возвращается при 404, что происходит при попытке создать конфликтующий заём (409), что при невалидном body (422) — и сегодняшняя практика целенаправленно требует именно такие тесты. Вторая ошибка — забыть откат (rollback) состояния БД после каждого теста: без него тесты начинают зависеть от порядка выполнения и от результатов друг друга, превращаясь в нестабильные (flaky) — тест то падает, то проходит без изменений в коде. Global exception handler для IntegrityError (например, попытка создать книгу с несуществующим author_id) — та же идея централизованной обработки ошибок, которую ты применишь в Express на следующей неделе через error-middleware: одно место в коде решает, как любая непойманная ошибка конкретного типа превращается в понятный HTTP-ответ.

                                                                                                                Читать:

                                                                                                                • FastAPI Testing
                                                                                                                • @@ -315,7 +333,7 @@

                                                                                                                  Практика (лайт / MVP)

                                                                                                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                  Если застрял

                                                                                                                  -

                                                                                                                  Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                  +

                                                                                                                  Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                  Git

                                                                                                                  • Закоммить изменения дня: git add week-18/git commit -m "week 18 day 125: pytest suite and error handlers"
                                                                                                                  • @@ -328,14 +346,17 @@

                                                                                                                    Ловушки


                                                                                                                    День 126 (Вс): Ревью и документация API

                                                                                                                    -

                                                                                                                    Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                    -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                    +

                                                                                                                    Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                    +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                    Связь с проектом: шаг к Library REST API

                                                                                                                    Теория

                                                                                                                    OpenAPI schema FastAPI генерирует из type hints и Pydantic — docs всегда синхронны с кодом, если ты дисциплинирован. README capstone-уровня: архитектура слоёв (routes → crud → models → db), env vars, curl-примеры, запуск postgres через docker. Postman collection — ручное тестирование для демо.

                                                                                                                    12 Factor App: config через environment, не hardcode. .env.example без секретов. Mermaid-диаграмма слоёв в README помогает объяснить проект за 2 минуты. Логирование через logging module: INFO в production, DEBUG в dev.

                                                                                                                    Финальный прогон: pytest, uvicorn, ручная проверка Swagger. Library REST API — шаблон для Express на нед. 19 и DevHub на нед. 22. Тег week-18-done завершает первый production-like Python backend.

                                                                                                                    +

                                                                                                                    Ментальная модель для ревью-дня: README и OpenAPI-документация — это витрина твоего проекта. Первые две минуты, которые незнакомый разработчик (или нанимающий менеджер) проводит с репозиторием, определяют, доверяет ли он остальному коду. Хорошо структурированный README с архитектурной диаграммой и curl-примерами говорит «этот человек умеет думать о других разработчиках», даже если он ни разу не прочитает исходники.

                                                                                                                    +

                                                                                                                    Дисциплина документирования, которую ты закрепляешь сегодня — env vars, архитектура слоёв, инструкции запуска, — это не разовая задача для этого проекта: ты буквально повторишь тот же набор артефактов для Express-проекта на неделе 19 и для capstone DevHub на неделе 22, так что сегодняшний README становится шаблоном, который экономит время трижды.

                                                                                                                    +

                                                                                                                    Частое заблуждение — считать, что автоматически сгенерированный Swagger (/docs) полностью заменяет README. Swagger прекрасно показывает что доступно (endpoints, схемы, параметры), но не объясняет как поднять проект с нуля — какие переменные окружения нужны, как накатить миграции, откуда взять seed-данные и в каком порядке запускать команды. Именно поэтому оба артефакта нужны вместе, и критерий «структура проекта понятна новому разработчику» проверяется человеком, а не автогенерацией. Логирование через стандартный модуль logging (а не print) — ещё одна деталь взросления проекта: INFO в продакшене и DEBUG в разработке позволяют управлять шумом логов без правки кода, просто переменной окружения. Принцип 12 Factor App («конфигурация через переменные окружения, а не хардкод») — ещё одна деталь, которая перестаёт быть абстрактной рекомендацией и становится практическим требованием, как только проект нужно развернуть в контейнере: .env.example документирует, какие переменные обязательны, не раскрывая ни одного реального секрета.

                                                                                                                    Читать:

                                                                                                                    • OpenAPI
                                                                                                                    • @@ -366,7 +387,7 @@

                                                                                                                      Практика (лайт / MVP)

                                                                                                                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                      Если застрял

                                                                                                                      -

                                                                                                                      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                      +

                                                                                                                      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                      Git

                                                                                                                      • Закоммить изменения дня: git add week-18/git commit -m "week 18 day 126: API docs and Postman collection"
                                                                                                                      • diff --git a/docs/w/19.html b/docs/w/19.html index 5aa9bea..deeed1a 100644 --- a/docs/w/19.html +++ b/docs/w/19.html @@ -22,14 +22,17 @@

                                                                                                                        День 127 (Пн): Node.js — среда и модули

                                                                                                                        -

                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                        -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                        +

                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                        +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                        Связь с проектом: шаг к Express Notes API

                                                                                                                        Теория

                                                                                                                        Node.js — среда выполнения JavaScript вне браузера. Нет DOM и window, зато есть process, встроенные модули и npm-экосистема. Backend на Node разделяет язык с фронтендом — один TypeScript/JavaScript на обе стороны, но runtime другой: event loop libuv, не браузерный.

                                                                                                                        CommonJS (require) vs ES Modules (import) — выбери "type": "module" в package.json для современного стиля. import.meta.url + fileURLToPath заменяют __dirname в ESM. Встроенные модули: fs, path, http. process.argv — аргументы CLI, process.env — переменные окружения.

                                                                                                                        npm управляет зависимостями: package.json, semver, node_modules. npm scripts ("greet": "node scripts/greet.js") — стандартный способ запуска задач. .gitignore: node_modules, .env. fs.promises вместо callback — async/await без callback hell.

                                                                                                                        +

                                                                                                                        Ментальная модель: Node.js — это тот же JavaScript, что и в браузере, но перенесённый в другую «комнату». Нет window, document, DOM — вместо них файловая система, сеть, процессы операционной системы. Синтаксис языка (переменные, функции, промисы) идентичен тому, что ты писал во фронтенд-частях курса, а вот доступное окружение и стандартная библиотека — совершенно другие, ориентированные на серверные задачи.

                                                                                                                        +

                                                                                                                        Это разделение окружения — не просто теория для сегодняшнего дня: весь Express-сервер, который ты соберёшь на этой неделе, работает по тем же базовым принципам Node — process.env для конфигурации, fs.promises для чтения файлов, событийная модель без блокировки. А общий язык с фронтендом — одно из главных практических преимуществ Node-стека в реальных командах: один разработчик может писать и клиент, и сервер.

                                                                                                                        +

                                                                                                                        Частое заблуждение — свободно мешать require() (CommonJS) и import (ES Modules) в одном проекте, ожидая, что Node сам разберётся. На практике "type": "module" в package.json — это переключатель на весь пакет: если он выставлен, require() в .js-файлах перестаёт работать и нужно использовать import/export, а __dirname из CommonJS придётся заменить на fileURLToPath(import.meta.url). Смешение стилей — частый источник непонятных SyntaxError у новичков, и именно поэтому практика дня явно требует единый ESM-стиль во всём проекте. Ещё одна важная привычка — fs.promises вместо колбэков: старый стиль fs.readFile(path, (err, data) => {...}) легко превращается в «пирамиду проклятия» (callback hell) при вложенных операциях, тогда как await fs.promises.readFile(path) читается линейно, сверху вниз, как синхронный код, оставаясь при этом неблокирующим.

                                                                                                                        Читать:

                                                                                                                        • Node.js Introduction
                                                                                                                        • @@ -73,14 +76,17 @@

                                                                                                                          Ловушки


                                                                                                                          День 128 (Вт): Асинхронность в Node

                                                                                                                          -

                                                                                                                          Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                          -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                          +

                                                                                                                          Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                          +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                          Связь с проектом: шаг к Express Notes API

                                                                                                                          Теория

                                                                                                                          Асинхронность — сердце Node. Эволюция: callback → Promise → async/await. Event loop libuv обрабатывает I/O неблокирующе, но синхронный fs.readFileSync в сервере заморозит все запросы — используй async API. await без try/catch — необработанный rejection.

                                                                                                                          EventEmitter (on, emit, once) — основа многих Node API и паттерн pub/sub. process.on('unhandledRejection') ловит забытые rejections — настрой в entry point. util.promisify оборачивает legacy callback API в Promise — для понимания, не для нового кода.

                                                                                                                          File watcher на notes.json учит реагировать на изменения; SIGINT корректно останавливает watcher. Promise.all читает три файла параллельно. Замер sync vs async на 10 файлах — наглядная демонстрация блокировки main thread.

                                                                                                                          +

                                                                                                                          Ментальная модель event loop — один официант на много столиков. Официант (главный поток Node) не готовит блюдо сам: он передаёт заказ на кухню (файловую систему, сеть, таймер через libuv) и тут же идёт принимать заказ у следующего столика, а не стоит и ждёт готовности. Когда блюдо готово, официант возвращается и подаёт его — это и есть callback/promise resolution. Именно эта модель позволяет Node одним потоком обслуживать тысячи одновременных соединений.

                                                                                                                          +

                                                                                                                          Это критично для всего, что будет построено дальше: каждый route-обработчик в Express на этой неделе — асинхронная функция, и если внутри неё случайно окажется синхронный блокирующий вызов (fs.readFileSync на большом файле, тяжёлые вычисления в цикле), это заморозит обработку всех остальных пользователей сервера одновременно, а не только текущий запрос — потому что официант всего один. EventEmitter с методами on, emit, once — ещё один слой этой же модели: множество встроенных Node API (потоки, HTTP-сервер) построены на событиях, и понимание паттерна pub/sub здесь напрямую объясняет, как работают, например, обработчики req.on('data', ...) при чтении тела запроса вручную.

                                                                                                                          +

                                                                                                                          Частое заблуждение — думать, что async/await сам по себе даёт параллелизм. await внутри функции лишь приостанавливает выполнение этой функции до готовности промиса, но следующая строка кода не начнёт выполняться, пока не завершится текущая — если нужно выполнить три независимые операции одновременно, необходим явный Promise.all([p1, p2, p3]), а последовательные await одна за другой выполнятся строго по очереди, теряя выгоду от параллельного I/O. Вторая типичная ошибка — забыть try/catch вокруг await: непойманный rejected promise превращается в unhandledRejection, который в новых версиях Node может привести к аварийному завершению процесса. Настройка process.on('unhandledRejection', ...) в точке входа приложения — не избыточная предосторожность, а страховка от того, что один забытый catch где-то в глубине кода уронит весь сервер целиком.

                                                                                                                          Читать:

                                                                                                                          • Event Loop
                                                                                                                          • @@ -111,7 +117,7 @@

                                                                                                                            Практика (лайт / MVP)

                                                                                                                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                            Если застрял

                                                                                                                            -

                                                                                                                            UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                            +

                                                                                                                            Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                            Git

                                                                                                                            • Закоммить изменения дня: git add week-19/git commit -m "week 19 day 128: async file watcher and error handling"
                                                                                                                            • @@ -124,14 +130,17 @@

                                                                                                                              Ловушки


                                                                                                                              День 129 (Ср): Express — REST API основы

                                                                                                                              -

                                                                                                                              Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                              -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                              +

                                                                                                                              Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                              +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                              Связь с проектом: шаг к Express Notes API

                                                                                                                              Теория

                                                                                                                              Express — минималистичный HTTP-фреймворк поверх Node http. app.get/post/put/delete маппят метод + путь на handler. req.params — path params, req.query — query string, req.body — JSON после express.json() middleware. Без body parser req.body будет undefined — классическая ловушка.

                                                                                                                              HTTP semantics: 200 OK, 201 Created, 204 No Content (DELETE без body), 400 Bad Request, 404 Not Found. Раздели app.js (конфигурация, middleware, routes) и server.js (listen) — app экспортируется для тестов. nodemon автоперезапускает в dev.

                                                                                                                              CRUD /api/notes с хранением в JSON-файле — мост к PostgreSQL завтра. Единый формат ответа { data } или { error: { message } } упрощает фронтенд. RESTful URLs: существительные, не глаголы.

                                                                                                                              +

                                                                                                                              Ментальная модель Express — конвейер middleware. Каждый входящий запрос проходит по цепочке функций-станций (loggerexpress.json() → маршруты → обработка 404 → обработчик ошибок), и каждая станция может прочитать/изменить запрос, ответить сразу или передать управление дальше через next(). Порядок подключения middleware в коде буквально определяет порядок их выполнения — это не декларативная конфигурация, а императивная последовательность.

                                                                                                                              +

                                                                                                                              Разделение app.js (конфигурация приложения) и server.js (запуск через listen) — не формальность: это тот же принцип тестируемости, что и TestClient в FastAPI на предыдущей неделе — app можно импортировать в тесты и слать в него запросы напрямую, без реального сетевого порта, что делает автотесты (день 133 и практика проекта) быстрыми и надёжными.

                                                                                                                              +

                                                                                                                              Частое заблуждение новичков — писать POST-обработчик, обращаться к req.body и получать undefined, не понимая почему: без подключённого express.json() middleware Express не парсит тело запроса автоматически — это осознанное архитектурное решение фреймворка, а не баг. Вторая распространённая ошибка — сваливать все маршруты в один растущий app.js на сотни строк вместо разделения по ресурсам (routes/notes.js, routes/authors.js), что уже на следующей неделе (после появления PostgreSQL) станет неуправляемым. Единый формат ответа ({ data } для успеха, { error: { message } } для ошибки) — небольшая деталь с большим эффектом: фронтенд может написать один универсальный обработчик ответов вместо разбора уникальной формы JSON для каждого отдельного endpoint. HTTP-семантика статусов из практики дня — тоже часть этого контракта: 201 Created сообщает фронтенду «ресурс появился, можно обновить список», а 204 No Content на DELETE явно говорит «операция прошла успешно, но отвечать нечем» — разница, которая имеет значение для клиентского кода, реагирующего на статус, а не только на тело ответа.

                                                                                                                              Читать:

                                                                                                                              • Express Hello World
                                                                                                                              • @@ -162,7 +171,7 @@

                                                                                                                                Практика (лайт / MVP)

                                                                                                                                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                Если застрял

                                                                                                                                -

                                                                                                                                Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                +

                                                                                                                                Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                Git

                                                                                                                                • Закоммить изменения дня: git add week-19/git commit -m "week 19 day 129: Express CRUD notes in-memory JSON"
                                                                                                                                • @@ -175,14 +184,17 @@

                                                                                                                                  Ловушки


                                                                                                                                  День 130 (Чт): Middleware, валидация, ошибки

                                                                                                                                  -

                                                                                                                                  Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                  -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                  +

                                                                                                                                  Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                  +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                  Связь с проектом: шаг к Express Notes API

                                                                                                                                  Теория

                                                                                                                                  Middleware в Express — функции (req, res, next) в цепочке. Порядок критичен: logger → express.json() → routes → 404 handler → error middleware (4 аргумента: err, req, res, next). next() передаёт управление дальше; next(err) — в error handler.

                                                                                                                                  Zod валидирует body с TypeScript inference: title min 1 символ, body optional. При ошибке — 400 с zodError.flatten(). Centralized error handler возвращает JSON { error: { code, message } } — единый контракт для клиента. morgan логирует HTTP-запросы в dev.

                                                                                                                                  404 handler для неизвестных routes — последний middleware перед error handler. Custom logger с duration (Date.now до/после) дополняет morgan. Error middleware без 4 параметров Express не распознает — не вызовется.

                                                                                                                                  +

                                                                                                                                  Ментальная модель порядка middleware — фильтры кофемашины: если поставить фильтр валидации до того, как вода (тело запроса) прошла через парсер (express.json()), фильтр получит пустоту вместо данных и либо пропустит мусор, либо сломается непредсказуемо. Порядок регистрации middleware в Express — это не стилистическое предпочтение, а часть логики приложения: express.json() обязан идти раньше любого middleware, читающего req.body.

                                                                                                                                  +

                                                                                                                                  Формат централизованной ошибки { error: { code, message } }, который ты вводишь сегодня, — не изобретение с нуля: это прямая параллель HTTPException + response_model из FastAPI на прошлой неделе. Оба стека решают одну и ту же задачу — дать фронтенду предсказуемый, единообразный контракт ошибок независимо от того, какой именно endpoint и какая причина сбоя. Сравнение этих двух подходов в конце недели наглядно покажет, что архитектурная идея важнее конкретного синтаксиса фреймворка.

                                                                                                                                  +

                                                                                                                                  Частое и коварное заблуждение — думать, что любую функцию с (req, res, next) можно превратить в обработчик ошибок, если просто вызвать её после остальных. Express распознаёт error-middleware исключительно по количеству аргументов — ровно четыре: (err, req, res, next). Функция с тремя параметрами, даже поставленная в конце цепочки, никогда не будет вызвана как error handler — это тихая, трудноуловимая ошибка, потому что сам код не падает, просто ошибки остаются необработанными. Вторая ошибка — забыть вызвать next(err) в обычном middleware при перехвате исключения, из-за чего запрос «зависает» без ответа клиенту. morgan в режиме 'dev' дополняет ручной логгер: он выводит метод, путь, статус-код и время ответа компактной цветной строкой, что удобно при локальной разработке, тогда как 'combined'-формат ближе к тому, что нужно собирать в продакшен-логах.

                                                                                                                                  Читать:

                                                                                                                                  • Writing middleware
                                                                                                                                  • @@ -213,7 +225,7 @@

                                                                                                                                    Практика (лайт / MVP)

                                                                                                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                    Если застрял

                                                                                                                                    -

                                                                                                                                    Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                    +

                                                                                                                                    Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                                                    Git

                                                                                                                                    • Закоммить изменения дня: git add week-19/git commit -m "week 19 day 130: Zod validation and error middleware"
                                                                                                                                    • @@ -226,14 +238,17 @@

                                                                                                                                      Ловушки


                                                                                                                                      День 131 (Пт): Express + PostgreSQL

                                                                                                                                      -

                                                                                                                                      Время (полный): ~50м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                      -Время (лайт): ~20м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                      +

                                                                                                                                      Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                      +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                      Связь с проектом: шаг к Express Notes API

                                                                                                                                      Теория

                                                                                                                                      node-postgres (pg) — драйвер PostgreSQL для Node. Pool переиспользует соединения под нагрузкой; new Client() на каждый запрос — антипаттерн. pool.query('SELECT * FROM notes WHERE id = $1', [id]) — placeholders $1, $2 защищают от SQL injection.

                                                                                                                                      DATABASE_URL=postgresql://user:pass@host:5432/db из .env через dotenv. Prisma — ORM-альтернатива (обзор); на этой неделе raw pg учит SQL и placeholders. Graceful shutdown: pool.end() на SIGTERM.

                                                                                                                                      Перепиши notes API с JSON-файла на таблицу notes(id, title, body, created_at). schema.sql + migrate script. Все запросы только через pool.query с массивом параметров — template strings в SQL запрещены.

                                                                                                                                      +

                                                                                                                                      Ментальная модель Pool — парковка с несколькими свободными местами вместо строительства нового гаража под каждую машину. new Client() на каждый запрос означает установление нового TCP-соединения к PostgreSQL при каждом HTTP-запросе — дорого и не масштабируется под нагрузкой. Pool заранее держит несколько открытых соединений, выдаёт свободное на время запроса и возвращает обратно, а не закрывает — ровно тот же принцип переиспользования ресурсов, что и session-per-request в SQLAlchemy на прошлой неделе.

                                                                                                                                      +

                                                                                                                                      Плейсхолдеры $1, $2 в node-postgres — это тот же самый принцип безопасности, который ты уже видел как ? в sqlite3 (неделя 16) и %s в psycopg2 (неделя 17): разный синтаксис, одна и та же идея — данные передаются драйверу отдельно от текста запроса, и СУБД никогда не путает пользовательский ввод с кодом SQL. Три экосистемы, три синтаксиса, один принцип — это стоит запомнить как универсальное правило, а не деталь конкретной библиотеки.

                                                                                                                                      +

                                                                                                                                      Частое заблуждение — считать, что «ручная» экранизация кавычек в строке перед вставкой в SQL через шаблонный литерал (`WHERE name = '${escaped}'`) достаточно безопасна. Единственный надёжный способ защититься от SQL injection — параметризованные запросы; любая самодельная санитизация рано или поздно пропустит edge case (Unicode-трюки, вложенные кавычки, null-байты). Вторая ошибка — не закрывать Pool при остановке приложения (pool.end() на SIGTERM), из-за чего процесс может зависать при попытке штатной остановки, а открытые соединения — накапливаться на стороне PostgreSQL. Перенос notes API с JSON-файла на настоящую таблицу — не просто смена хранилища: он заставляет явно продумать схему (id, title, body, created_at) и написать schema.sql вместо неявной структуры JS-объекта, что дисциплинирует так же, как проектирование схемы «Библиотека» на прошлой неделе.

                                                                                                                                      Читать:

                                                                                                                                      • node-postgres
                                                                                                                                      • @@ -277,14 +292,17 @@

                                                                                                                                        Ловушки


                                                                                                                                        День 132 (Сб): Структура проекта и роутеры

                                                                                                                                        -

                                                                                                                                        Время (полный): ~50м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                        -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                        +

                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                        +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                        Связь с проектом: шаг к Express Notes API

                                                                                                                                        Теория

                                                                                                                                        Express Router модульно группирует маршруты: notes.routes.js монтируется с prefix /api/notes. Layered architecture: routes (тонкие) → controllers (HTTP) → services (бизнес-логика) → db (SQL). Бизнес-логика в route handler не тестируется — вынеси в service.

                                                                                                                                        dotenv загружает secrets из .env; NODE_ENV=development|production меняет поведение (morgan 'dev' vs 'combined'). Health check GET /api/health возвращает { status, db: 'ok'|'down', uptime } — нужен для Docker и мониторинга. 503 если БД недоступна.

                                                                                                                                        Graceful shutdown: SIGTERM → server.close()pool.end(). package-lock.json в git — воспроизводимые сборки. README описывает слои папок — onboarding нового разработчика.

                                                                                                                                        +

                                                                                                                                        Ментальная модель layered-архитектуры — песочные часы: HTTP-специфичные детали (заголовки, статусы, парсинг запроса) сужаются к чистой бизнес-логике в узком горлышке (service), а затем снова расширяются к деталям хранения данных (db). Каждый слой знает только о соседнем: controller не знает, как устроен SQL-запрос внутри service, а service не знает, что вызвавший его код — это HTTP-запрос, а не, например, cron-задача или CLI-команда.

                                                                                                                                        +

                                                                                                                                        Это разделение — не Node-специфичная причуда: это буквально та же архитектура routers → crud → models → db, которую ты собрал в FastAPI на прошлой неделе, только с другими именами слоёв. Узнавание одного и того же архитектурного паттерна в двух разных языках и фреймворках — куда более ценный навык, чем запоминание синтаксиса одного конкретного стека, и именно это делает тебя способным быстро освоить третий, четвёртый фреймворк в будущем.

                                                                                                                                        +

                                                                                                                                        Частое заблуждение — писать бизнес-логику прямо внутри route-обработчика «раз уж всё равно там нужен доступ к req и res». Логика, зашитая в controller, не может быть протестирована без поднятия HTTP-сервера и не может быть переиспользована, если та же операция понадобится, например, из cron-задачи. Вторая ошибка — делать health check, который слепо возвращает 200 OK, не проверяя реальную доступность БД: оркестраторы вроде Docker или Kubernetes используют health check, чтобы решить, направлять ли трафик на этот инстанс, и «фальшиво здоровый» сервис без реального подключения к БД будет продолжать получать запросы, которые обречены на ошибку. Graceful shutdown (SIGTERMserver.close()pool.end()) — финальный штрих той же дисциплины: сервер должен успеть корректно завершить уже начатые запросы и закрыть соединения с БД перед остановкой, а не обрубать их резко, теряя данные в процессе.

                                                                                                                                        Читать:

                                                                                                                                        • Express Router
                                                                                                                                        • @@ -315,7 +333,7 @@

                                                                                                                                          Практика (лайт / MVP)

                                                                                                                                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                          Если застрял

                                                                                                                                          -

                                                                                                                                          Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                          +

                                                                                                                                          Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                          Git

                                                                                                                                          • Закоммить изменения дня: git add week-19/git commit -m "week 19 day 132: layered architecture and health check"
                                                                                                                                          • @@ -328,14 +346,17 @@

                                                                                                                                            Ловушки


                                                                                                                                            День 133 (Вс): Ревью Node.js и сравнение с FastAPI

                                                                                                                                            -

                                                                                                                                            Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                            -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                            +

                                                                                                                                            Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                            +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                            Связь с проектом: шаг к Express Notes API

                                                                                                                                            Теория

                                                                                                                                            Ревью недели — сравнение двух backend-стеков, которые ты теперь знаешь. FastAPI: автодоки, Pydantic, async, Python ecosystem. Express: минимализм, npm, один язык с React. Для I/O-bound оба отличны; CPU-bound тяжёлая работа чаще уходит в Python или отдельный worker.

                                                                                                                                            npm scripts best practices: start (production), dev (nodemon), test, db:migrate. Postman collection — демо и ручное QA. Skeleton auth.routes.js — мост к неделе 20. npm audit показывает уязвимости в зависимостях.

                                                                                                                                            Сравнительная таблица FastAPI vs Express по 10 критериям учит аргументировать выбор стека. Express Notes API — parity с Library REST API недели 18: те же статусы, формат ошибок, layered structure. Тег week-19-done.

                                                                                                                                            +

                                                                                                                                            Ментальная модель для сравнения стеков — две разные клавиатуры, подключённые к одному и тому же роялю. FastAPI и Express предлагают разную эргономику (типизация из коробки против гибкости без неё, автогенерация Swagger против ручной настройки, async Python против нативно-асинхронного JS), но производят одну и ту же «музыку» — REST-ресурсы, HTTP-статусы, JSON-контракты. Разработчик, освоивший оба, видит сквозь синтаксис общую архитектуру.

                                                                                                                                            +

                                                                                                                                            Умение аргументированно сравнить два стека по конкретным критериям (типизация, экосистема библиотек, производительность под нагрузкой, порог входа для команды, зрелость инструментов) — это именно тот навык, который проверяют на технических интервью вопросом «почему вы выбрали X, а не Y», и именно поэтому сравнительная таблица — не формальность, а тренировка аргументации, которая пригодится за пределами учебного проекта.

                                                                                                                                            +

                                                                                                                                            Частое заблуждение — искать единственно «правильный» стек и считать все остальные хуже. На практике выбор между FastAPI и Express в реальной команде почти никогда не решается голым сравнением фреймворков: он зависит от опыта команды, существующего кода, экосистемы (например, ML/data-задачи почти всегда тянут к Python), требований к производительности и скорости найма разработчиков. Skeleton auth.routes.js с заглушками — не проходной пункт практики, а прямой мост к теме аутентификации, которую ты будешь реализовывать уже на следующей неделе, причём в обоих стеках параллельно. npm audit в практике дня — ещё одна привычка, которая пригодится за пределами курса: открытый исходный код зависимостей означает и открытые уязвимости, и регулярная проверка (а не разовая на старте проекта) — часть базовой гигиены production-приложения.

                                                                                                                                            Читать:

                                                                                                                                            • npm scripts
                                                                                                                                            • @@ -366,7 +387,7 @@

                                                                                                                                              Практика (лайт / MVP)

                                                                                                                                              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                              Если застрял

                                                                                                                                              -

                                                                                                                                              Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                              +

                                                                                                                                              Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                              Git

                                                                                                                                              • Закоммить изменения дня: git add week-19/git commit -m "week 19 day 133: docs, Postman, auth skeleton"
                                                                                                                                              • diff --git a/docs/w/20.html b/docs/w/20.html index 60ead66..ca498be 100644 --- a/docs/w/20.html +++ b/docs/w/20.html @@ -22,14 +22,17 @@

                                                                                                                                                День 134 (Пн): Аутентификация и хеширование паролей

                                                                                                                                                -

                                                                                                                                                Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                +

                                                                                                                                                Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                Связь с проектом: шаг к Secure Notes

                                                                                                                                                Теория

                                                                                                                                                Authentication отвечает на вопрос «кто ты?» — проверка личности (логин/пароль). Authorization — «что тебе можно?» — права на ресурсы. Не путай: успешный login не означает доступ ко всем endpoints. Пароли никогда не хранятся в plain text, даже в dev-базе.

                                                                                                                                                bcrypt (Node) и passlib с bcrypt (Python) — adaptive hashing с встроенным salt. Salt rounds 10–12 — баланс безопасность/скорость. При register: validate email → hash(password, 12) → store password_hash. При login: compare(plain, hash). SHA256 без salt уязвим к rainbow tables.

                                                                                                                                                Registration flow: дубликат email → 409 Conflict. Login: неверный пароль → 401 Unauthorized с generic message «Invalid credentials» — не раскрывай, существует ли email. Пароль не логируй и не возвращай в JSON response.

                                                                                                                                                +

                                                                                                                                                Ментальная модель: хеш пароля — это цифровой отпечаток, а не сейф с ключом. Ты не «открываешь» hash обратно в пароль — bcrypt при login заново хеширует введённый пароль с тем же salt и сравнивает отпечатки. Это принципиально отличает hashing от encryption, где данные можно расшифровать зная ключ. Для junior backend-роли эта тема — почти гарантированный вопрос на собеседовании: «как ты хранишь пароли?» — и неправильный ответ («шифрую AES») сразу выдаёт незрелость. На практике каждая компания, где есть пользователи, должна закрыть этот вопрос в первый день продакшена.

                                                                                                                                                +

                                                                                                                                                Классический пример цены ошибки — утечка LinkedIn 2012 года: пароли хранились как unsalted SHA1, и после взлома миллионы паролей были восстановлены за часы перебором по rainbow tables. Частое заблуждение новичков — «добавлю к паролю секретную строку и захеширую SHA256, этого достаточно» — но без cost-фактора (salt rounds) современные GPU перебирают миллиарды SHA256-хешей в секунду, а bcrypt намеренно медленный и настраиваемый. Именно этот механизм регистрации ты сегодня реализуешь в Secure Notes, и тот же код позже переиспользуешь в DevHub capstone (неделя 22, день 151) — прочный фундамент экономит часы отладки в финале роадмапа.

                                                                                                                                                +

                                                                                                                                                Для продакшена важна и обратная сторона: слишком высокий cost factor (например, 15+ раундов) замедляет login до заметных пользователю секунд и создаёт нагрузку на CPU при пиковой регистрации — поэтому 10–12 раундов остаётся индустриальным стандартом, а не произвольным числом. Держи это в голове при код-ревью чужого auth-кода: cost factor — не «чем больше, тем безопаснее», а сознательный компромисс между защитой и latency бюджетом сервиса.

                                                                                                                                                Читать:

                                                                                                                                                • bcrypt (Node)
                                                                                                                                                • @@ -73,14 +76,17 @@

                                                                                                                                                  Ловушки


                                                                                                                                                  День 135 (Вт): JWT — выдача и проверка токенов

                                                                                                                                                  -

                                                                                                                                                  Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                  -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                  +

                                                                                                                                                  Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                  +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                  Связь с проектом: шаг к Secure Notes

                                                                                                                                                  Теория

                                                                                                                                                  JWT (JSON Web Token) — компактный способ передавать claims между клиентом и сервером. Структура: header.payload.signature. Подпись (HMAC SHA256) гарантирует целостность; payload base64-decodable — не клади пароли и PII. Стандарт передачи: Authorization: Bearer <token>.

                                                                                                                                                  Access token TTL 15min–1h; refresh token — отдельный долгоживущий механизм (обзор). JWT_SECRET в .env — минимум 32 случайных байта; при утечке — rotate немедленно. Payload: sub (user id), exp, iat. Явно указывай algorithm: 'HS256' — алгоритм none — уязвимость.

                                                                                                                                                  Middleware authenticateToken verify JWT и кладёт req.user = { id, email }. Protected routes читают user_id из token, не из body/query — иначе IDOR. Expired token → 401. Тест с TTL 1 секунда проверяет expiration.

                                                                                                                                                  +

                                                                                                                                                  Ментальная модель: JWT — это подписанная справка, а не запечатанный конверт. Любой может прочитать payload через base64-decode (проверь на jwt.io), но подделать подпись без секрета невозможно — поэтому в payload никогда не кладут пароли, номера карт или другие секреты, только неконфиденциальные claims вроде user id и роли. На собеседованиях junior-разработчиков часто путают JWT с session cookie: JWT stateless (сервер ничего не хранит, просто проверяет подпись), а session требует хранилища на сервере — эта разница определяет, как система масштабируется горизонтально.

                                                                                                                                                  +

                                                                                                                                                  Конкретный пример уязвимости: если backend принимает algorithm: none или не проверяет alg вообще, атакующий может подделать токен с любым payload и получить admin-доступ — это реальная категория уязвимостей, встречавшаяся в популярных JWT-библиотеках. Частое заблуждение — «раз токен подписан, значит зашифрован и безопасен для любых данных» — на деле подпись гарантирует только целостность, не конфиденциальность. Middleware, который ты пишешь сегодня, — это тот же паттерн защищённых маршрутов, который в неделе 22 (день 151) масштабируется на весь DevHub: req.user из verified JWT, а не из тела запроса, закрывает целый класс IDOR-уязвимостей.

                                                                                                                                                  +

                                                                                                                                                  Для продакшена короткий TTL access token (15 минут–1 час) — не паранойя, а ограничение окна атаки: если токен украли через XSS или перехват трафика, он бесполезен уже через час. Полноценный refresh-token механизм с ротацией — тема отдельного, более продвинутого модуля, но важно понимать саму идею уже сейчас: access token — расходный материал, а не постоянный пропуск, который выдаётся один раз и живёт вечно.

                                                                                                                                                  Читать:

                                                                                                                                                  • JWT Introduction
                                                                                                                                                  • @@ -111,7 +117,7 @@

                                                                                                                                                    Практика (лайт / MVP)

                                                                                                                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                    Если застрял

                                                                                                                                                    -

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

                                                                                                                                                    +

                                                                                                                                                    Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                    Git

                                                                                                                                                    • Закоммить изменения дня: git add week-20/git commit -m "week 20 day 135: JWT middleware and protected routes"
                                                                                                                                                    • @@ -124,14 +130,17 @@

                                                                                                                                                      Ловушки


                                                                                                                                                      День 136 (Ср): OWASP Top 10 — практическая защита

                                                                                                                                                      -

                                                                                                                                                      Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                      -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                      +

                                                                                                                                                      Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                      +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                      Связь с проектом: шаг к Secure Notes

                                                                                                                                                      Теория

                                                                                                                                                      OWASP Top 10 — карта самых частых уязвимостей веб-приложений. Ты уже закрываешь injection parameterized queries (нед. 17–19). Broken authentication — слабые пароли, утечка session. XSS — неэкранированный user-generated HTML; escape output, DOMPurify для rich text.

                                                                                                                                                      Helmet.js выставляет security headers: X-Content-Type-Options, X-Frame-Options, CSP basics. express-rate-limit на /auth/login: 5 попыток / 15 мин per IP → 429 Too Many Requests — защита от brute-force. CORS: явный whitelist origins; origin: '*' с credentials — небезопасно.

                                                                                                                                                      Аудит: .env в .gitignore, .env.example без секретов, проверь git log на утечки. security-audit.md с чеклистом 10 пунктов — deliverable недели. CORS в dev: allow только http://localhost:5173.

                                                                                                                                                      +

                                                                                                                                                      Ментальная модель — думай про безопасность как про слоёный пирог (defense in depth): ни один слой не идеален сам по себе, но вместе hash + JWT + rate limit + headers + CORS перекрывают друг друга. Для junior-позиции знание OWASP Top 10 — не академическое упражнение, а практический чеклист, который спрашивают на security-ориентированных собеседованиях и которым реально пользуются на code review в компаниях с compliance-требованиями (SOC2, PCI DSS).

                                                                                                                                                      +

                                                                                                                                                      Конкретный пример: без rate limit на /auth/login атакующий может перебрать пароли скриптом за секунды — 5 попыток / 15 минут превращают brute-force в непрактичную атаку. Частое заблуждение начинающих — «у меня маленький pet-проект, кому он нужен» — но боты сканируют весь интернет автоматически, а не выбирают жертву вручную; открытый .env в публичном репозитории находят за минуты. Чеклист security-audit.md, который ты заполняешь сегодня, — прямой прообраз SECURITY.md в DevHub capstone (неделя 22): те же 10 пунктов OWASP, но уже против реального multi-user приложения с репутацией на кону.

                                                                                                                                                      +

                                                                                                                                                      Для продакшена CORS — не разовая настройка, а живой список, который меняется с каждым новым окружением: dev допускает localhost:5173, staging — свой домен, прод — финальный домен фронтенда. Забытая запись в whitelist после деплоя — одна из самых частых причин, почему «API работает в Postman, но не в браузере»: curl и Postman не проверяют CORS вообще, эту проверку делает только браузер, поэтому баг обнаруживается лишь при реальном использовании интерфейса. Держи чеклист OWASP под рукой не как разовое упражнение, а как привычку code review для каждого нового endpoint.

                                                                                                                                                      Читать:

                                                                                                                                                      • OWASP Top 10
                                                                                                                                                      • @@ -162,7 +171,7 @@

                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                        Если застрял

                                                                                                                                                        -

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

                                                                                                                                                        +

                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                        Git

                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m "week 20 day 136: OWASP audit rate limit helmet"
                                                                                                                                                        • @@ -175,14 +184,17 @@

                                                                                                                                                          Ловушки


                                                                                                                                                          День 137 (Чт): Тестирование backend — pytest

                                                                                                                                                          -

                                                                                                                                                          Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                          -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                          +

                                                                                                                                                          Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                          +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                          Связь с проектом: шаг к Secure Notes

                                                                                                                                                          Теория

                                                                                                                                                          Backend-тесты ловят регрессии в auth и authorization. pytest + FastAPI TestClient или supertest для Express — HTTP без реального порта. Fixtures: create_user(), auth_headers(token). Test DB изолирована: отдельная schema или rollback per test — никогда production.

                                                                                                                                                          Arrange-Act-Assert в каждом тесте. Покрой: register success, duplicate 409, wrong password 401, protected 401 без token, 200 с token, user A не видит notes user B. conftest.py — shared setup. pytest --cov=app показывает пробелы.

                                                                                                                                                          Тесты не должны зависеть от порядка выполнения. Hardcoded JWT secret в тестах должен совпадать с app config. ≥ 10 тестов — минимум для Secure Notes. Flaky tests из shared DB без cleanup — исправь до merge.

                                                                                                                                                          +

                                                                                                                                                          Ментальная модель: тест — это исполняемая спецификация поведения, а не бюрократическая формальность. Arrange-Act-Assert структурирует мышление: подготовь данные, вызови действие, проверь результат — один тест проверяет одну вещь. Для junior-разработчика умение писать тесты на auth и authorization — сигнал зрелости для нанимающего менеджера: код без тестов на security-критичные пути в реальной компании не пройдёт code review.

                                                                                                                                                          +

                                                                                                                                                          Конкретный пример пользы: тест «user A не видит notes user B» ловит IDOR-баг ещё до продакшена — без него такая уязвимость обнаруживается только в security-инциденте или пентесте, что стоит репутации и денег. Частое заблуждение новичков — «я протестировал руками через Postman, тестов достаточно» — но ручное тестирование не защищает от регрессий при следующем рефакторинге, а автоматические тесты запускаются на каждый commit. Инфраструктура тестов, которую ты строишь сегодня (fixtures, conftest.py, изоляция БД), — это ровно то, что масштабируется в неделе 22 (день 153) до ≥15 pytest-тестов в CI capstone-проекта.

                                                                                                                                                          +

                                                                                                                                                          Для продакшена тесты выполняют вторую важную функцию — они документируют ожидаемое поведение системы точнее, чем любой комментарий в коде: новый разработчик, зашедший в проект, читает тесты, чтобы понять контракт API, а не гадает по названиям функций. pytest --cov=app показывает не «сколько строк покрыто», а скорее карту слепых зон — мест, куда никто не заглядывал тестами, и именно там чаще всего прячутся баги, которые всплывают в проде. Читай отчёт покрытия критически: 100% покрытия не гарантирует отсутствие багов, если assertions в тестах слабые, но пробелы в покрытии почти всегда указывают на риск.

                                                                                                                                                          Читать:

                                                                                                                                                          • pytest
                                                                                                                                                          • @@ -213,7 +225,7 @@

                                                                                                                                                            Практика (лайт / MVP)

                                                                                                                                                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                            Если застрял

                                                                                                                                                            -

                                                                                                                                                            Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                            +

                                                                                                                                                            Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                                                                            Git

                                                                                                                                                            • Закоммить изменения дня: git add week-20/git commit -m "week 20 day 137: pytest auth and notes tests"
                                                                                                                                                            • @@ -226,14 +238,17 @@

                                                                                                                                                              Ловушки


                                                                                                                                                              День 138 (Пт): Тестирование frontend — Vitest

                                                                                                                                                              -

                                                                                                                                                              Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                              -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                              +

                                                                                                                                                              Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                              +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                              Связь с проектом: шаг к Secure Notes

                                                                                                                                                              Теория

                                                                                                                                                              Vitest — test runner, нативный для Vite-проектов, API совместим с Jest. React Testing Library (RTL) тестирует поведение с точки зрения пользователя: getByRole, getByLabelText, не getByClassName. userEvent симулирует реальные клики и ввод с клавиатуры.

                                                                                                                                                              Mock fetch через vi.fn() или global.fetch = vi.fn().mockResolvedValue(...) изолирует компоненты от API. Тестируй: Login submit шлёт credentials, ProtectedRoute редиректит без token, NotesList рендерит mock data, login 401 показывает ошибку. vi.mock() для модулей.

                                                                                                                                                              ≥ 8 component tests. vitest run в CI. Тестирование internal state вместо visible behavior — хрупкие тесты. Cleanup mocks в afterEach — иначе тесты влияют друг на друга.

                                                                                                                                                              +

                                                                                                                                                              Ментальная модель React Testing Library — «тестируй как пользователь, а не как разработчик»: пользователь не знает про internal state или имена CSS-классов, он видит кнопки, лейблы и текст на экране. Поэтому getByRole и getByLabelText устойчивее к рефакторингу компонента, чем getByClassName или проверка state напрямую. Для junior frontend-позиции это стандарт индустрии — большинство современных React-команд требуют RTL-подход в тестах.

                                                                                                                                                              +

                                                                                                                                                              Конкретный пример: если ты тестируешь wrapper.state.isLoggedIn === true вместо того, что видно на экране («Welcome» текст появился), рефакторинг компонента с useState на useReducer сломает тест, хотя поведение для пользователя не изменилось — это и есть хрупкий тест. Частое заблуждение — «чем больше моков, тем лучше изолирован тест» — избыточный mocking скрывает реальные баги интеграции; мокай только внешние границы (fetch, роутер), а не внутреннюю логику компонента. Компонентные тесты Login/ProtectedRoute/NotesList, которые ты пишешь сегодня, — прямой шаблон для тестов TaskList и NoteEditor в DevHub capstone (неделя 22, день 153), где потребуется уже ≥12 таких тестов.

                                                                                                                                                              +

                                                                                                                                                              Для продакшена связка Vitest + RTL особенно ценна на команде из нескольких frontend-разработчиков: когда кто-то меняет структуру JSX компонента ради рефакторинга, тесты, написанные через getByRole, продолжают проходить, а тесты через querySelector('.btn-submit') ломаются от простого переименования CSS-класса — разница напрямую влияет на то, сколько времени команда тратит на «починку зелёных тестов» после каждого рефакторинга вместо реальной разработки функциональности. Именно поэтому RTL стала де-факто стандартом тестирования React-компонентов в индустрии, а не просто одной из многих альтернатив — это первое, что спросят про фронтенд-тестирование на техническом собеседовании junior-разработчика.

                                                                                                                                                              Читать:

                                                                                                                                                              • Vitest
                                                                                                                                                              • @@ -277,14 +292,17 @@

                                                                                                                                                                Ловушки


                                                                                                                                                                День 139 (Сб): Интеграция auth frontend + backend

                                                                                                                                                                -

                                                                                                                                                                Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                +

                                                                                                                                                                Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                Связь с проектом: шаг к Secure Notes

                                                                                                                                                                Теория

                                                                                                                                                                Full-stack auth связывает JWT backend с React frontend. Token storage: localStorage прост, но уязвим к XSS; httpOnly cookie безопаснее, сложнее с CORS. Для учебного проекта localStorage + CSP + sanitize input — приемлемо; задокументируй trade-off в README.

                                                                                                                                                                AuthContext: user, token, login, logout, isLoading. api.ts wrapper подставляет Authorization: Bearer и на 401 очищает token + redirect /login. React Router <ProtectedRoute> оборачивает private pages. Token не в URL query string — утечёт в logs и history.

                                                                                                                                                                Full flow: register → login → create note → logout → login → note visible. User A не видит notes User B — проверь вручную и тестами. Axios interceptors или fetch wrapper — один вход для всех API calls.

                                                                                                                                                                +

                                                                                                                                                                Ментальная модель: думай о AuthContext как о единственном источнике правды про личность пользователя во всём React-дереве — компоненты не хранят свою копию token, а читают из контекста через useAuth(). Это устраняет рассинхронизацию состояния, когда один компонент думает, что пользователь залогинен, а другой — нет. Для реальной работы junior full-stack разработчика это один из первых архитектурных паттернов, который придётся освоить: почти любое SPA с авторизацией использует похожую структуру (Context/Redux/Zustand + protected routes).

                                                                                                                                                                +

                                                                                                                                                                Конкретный пример проблемы без единого api-wrapper: если каждый компонент делает свой fetch и сам добавляет заголовок, то при истечении токена придётся чинить логику логаута в десятке мест — а с interceptor это одна точка изменения. Частое заблуждение — «localStorage полностью безопасен для токенов» — на деле любой XSS на странице получает доступ к localStorage через localStorage.getItem, поэтому в проде банки и финтех используют httpOnly cookie; для учебного проекта localStorage допустим при условии осознанного trade-off, задокументированного в README. Этот же auth flow — Context, api wrapper, protected routes — ты соберёшь заново, но уже с нуля, в DevHub capstone (неделя 22, день 151), так что качество кода сегодня напрямую экономит время через две недели.

                                                                                                                                                                +

                                                                                                                                                                Для продакшена полезно явно проговорить trade-off хранения токена в коде и в README: это показывает ревьюеру портфолио, что решение осознанное, а не «забыл подумать про безопасность». Многие junior-кандидаты либо вообще не упоминают эту тему, либо копируют случайный код без понимания — а один абзац в README о том, почему выбран localStorage и какие меры снижают риск (CSP, sanitize, короткий TTL), выделяет проект среди типовых учебных.

                                                                                                                                                                Читать:

                                                                                                                                                                • OWASP Session Management
                                                                                                                                                                • @@ -315,7 +333,7 @@

                                                                                                                                                                  Практика (лайт / MVP)

                                                                                                                                                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                  Если застрял

                                                                                                                                                                  -

                                                                                                                                                                  Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                  +

                                                                                                                                                                  Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                  Git

                                                                                                                                                                  • Закоммить изменения дня: git add week-20/git commit -m "week 20 day 139: React auth integration"
                                                                                                                                                                  • @@ -328,14 +346,17 @@

                                                                                                                                                                    Ловушки


                                                                                                                                                                    День 140 (Вс): Ревью безопасности и CI

                                                                                                                                                                    -

                                                                                                                                                                    Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                    -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                    +

                                                                                                                                                                    Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                    +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                    Связь с проектом: шаг к Secure Notes

                                                                                                                                                                    Теория

                                                                                                                                                                    CI автоматизирует проверку качества на каждый push. GitHub Actions: matrix jobs для backend (pytest) и frontend (vitest run). Зелёный CI — сигнал, что main mergeable. Branch protection с require CI — best practice для команд (обзор).

                                                                                                                                                                    npm audit и pip audit сканируют known vulnerabilities в зависимостях. Critical без комментария или плана фикса — красный флаг для портфолио. Semgrep — static analysis (обзор). Sequence diagram auth flow в README объясняет архитектуру ревьюеру.

                                                                                                                                                                    Финальный security review по OWASP чеклисту. Обнови .env.example для backend и frontend. Smoke test checklist в README. Тег week-20-done — Secure Notes готов как шаблон для недель 21–22.

                                                                                                                                                                    +

                                                                                                                                                                    Ментальная модель: CI — это автоматический привратник качества, который проверяет код за тебя каждый раз, когда ты забываешь. Зелёный чек на GitHub — не формальность для галочки, а сигнал команде (или ревьюеру портфолио), что код прошёл минимальную планку: тесты, линтер, security-скан. Для junior-кандидата наличие рабочего CI pipeline в pet-проекте на GitHub — заметный плюс: рекрутеры и техлиды буквально открывают вкладку Actions, чтобы увидеть зелёную галочку до того, как откроют код.

                                                                                                                                                                    +

                                                                                                                                                                    Конкретный пример пользы: npm audit может найти критическую уязвимость в транзитивной зависимости, о существовании которой ты даже не знал — типичный кейс cascading vulnerability в node_modules. Частое заблуждение — «раз мой код написан безопасно, зависимости не важны» — но большая часть реальных production-инцидентов происходит именно через уязвимые библиотеки третьих сторон, а не собственный код. Workflow ci.yml, который ты пишешь сегодня, — это шаблон, который в неделе 21 расширится healthcheck-ами для Docker, а в неделе 22 (день 153) вырастет до полноценного pipeline с postgres service и двумя параллельными job — тег week-20-done фиксирует рабочую точку отсчёта для этого пути.

                                                                                                                                                                    +

                                                                                                                                                                    Для продакшена архитектурные решения без документации быстро забываются: через месяц ты сам не вспомнишь, почему выбран именно такой TTL токена или почему rate limit настроен на 5, а не на 10 попыток. Sequence diagram auth flow в README — не украшение, а инструмент передачи знаний будущему тебе или коллеге, который придёт поддерживать проект и не должен реверс-инжинирить логику по коду построчно.

                                                                                                                                                                    Читать:

                                                                                                                                                                    • GitHub Actions
                                                                                                                                                                    • @@ -366,7 +387,7 @@

                                                                                                                                                                      Практика (лайт / MVP)

                                                                                                                                                                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                      Если застрял

                                                                                                                                                                      -

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

                                                                                                                                                                      +

                                                                                                                                                                      Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                      Git

                                                                                                                                                                      • Закоммить изменения дня: git add week-20/git commit -m "week 20 day 140: CI workflow and security docs"
                                                                                                                                                                      • diff --git a/docs/w/21.html b/docs/w/21.html index 754e2bd..f0ed5c1 100644 --- a/docs/w/21.html +++ b/docs/w/21.html @@ -22,14 +22,17 @@

                                                                                                                                                                        День 141 (Пн): Связка Frontend + Backend

                                                                                                                                                                        -

                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                        -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                        +

                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                        +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                        Связь с проектом: шаг к Task Manager Docker

                                                                                                                                                                        Теория

                                                                                                                                                                        Full-stack начинается там, где фронтенд и бэкенд встречаются в браузере. Same-origin policy: localhost:5173 (Vite) и localhost:3000 (API) — разные origins. Браузер блокирует cross-origin fetch без заголовков CORS от сервера. Preflight OPTIONS запрос отправляется для «непростых» запросов.

                                                                                                                                                                        cors middleware в Express или CORSMiddleware в FastAPI с whitelist http://localhost:5173. VITE_API_URL — build-time переменная для фронтенда; DATABASE_URL — runtime для бэкенда. Vite proxy в dev обходит CORS, направляя /api на backend — same-origin для браузера.

                                                                                                                                                                        Замени localStorage tasks/notes на API CRUD — это суть недели. Проверь Network tab: нет CORS errors. .env.example для обоих проектов. Hardcoded localhost в production build — сломает deploy.

                                                                                                                                                                        +

                                                                                                                                                                        Ментальная модель: origin — это тройка (протокол, домен, порт), и браузер по умолчанию блокирует любой fetch между разными origin, если сервер явно не разрешил это через CORS-заголовки. Это защита пользователя, а не бага фреймворка — без same-origin policy любой сайт мог бы читать твою банковскую сессию через скрытый fetch. Для junior full-stack разработчика непонимание CORS — источник часа-двух бесполезной отладки почти в каждом первом проекте; умение быстро прочитать ошибку CORS в консоли и понять, на чьей она стороне (сервер не разрешил origin) — практический навык уровня middle.

                                                                                                                                                                        +

                                                                                                                                                                        Конкретный пример: если VITE_API_URL не имеет префикса VITE_, Vite просто не включит переменную в bundle — переменная будет undefined в runtime, и ошибка проявится не как CORS, а как fetch на undefined/api/tasks, что сбивает с толку новичков. Частое заблуждение — «CORS настраивается на клиенте» — на самом деле разрешение полностью на стороне сервера (заголовки Access-Control-Allow-Origin), клиент только соблюдает то, что разрешил браузер. Именно этот CORS-контракт между React-клиентом и API — фундамент для docker-compose сети в этой же неделе (день 145), где origin меняются на container hostnames, и для production deploy в DevHub capstone, где появится третий origin — Vercel domain.

                                                                                                                                                                        +

                                                                                                                                                                        Для продакшена preflight OPTIONS-запрос — источник ещё одной частой путаницы: браузер отправляет его автоматически перед «непростыми» запросами (с кастомными заголовками вроде Authorization или методом PUT/DELETE), и сервер должен явно ответить на OPTIONS без падения — иначе основной запрос до сервера вообще не дойдёт, а в Network tab будет видна только неудачная preflight-строка, что сбивает с толку при первой отладке.

                                                                                                                                                                        Читать:

                                                                                                                                                                        • CORS (MDN)
                                                                                                                                                                        • @@ -73,14 +76,17 @@

                                                                                                                                                                          Ловушки


                                                                                                                                                                          День 142 (Вт): Единый API-контракт и обработка ошибок

                                                                                                                                                                          -

                                                                                                                                                                          Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                          -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                          +

                                                                                                                                                                          Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                          +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                          Связь с проектом: шаг к Task Manager Docker

                                                                                                                                                                          Теория

                                                                                                                                                                          API contract — общий язык фронтенда и бэкенда. OpenAPI/Swagger — source of truth: типы, статусы, примеры. Единый формат ошибок { error: { code, message, details? } } упрощает парсинг на клиенте. 4xx — «ты сделал что-то не так», 5xx — «попробуй позже».

                                                                                                                                                                          Три UI-состояния на каждой data-fetching странице: loading (spinner), error (message + retry), empty (подсказка действия). services/api.ts — единый fetch wrapper с auth header и error parsing; не дублируй fetch в 10 компонентах. TypeScript types Task, ApiError в types/api.ts.

                                                                                                                                                                          Проверяй res.ok перед json() — иначе парсишь HTML error page как JSON. React Query/SWR — опционально для кеша и retry. Сверь frontend types с OpenAPI вручную или через openapi-typescript.

                                                                                                                                                                          +

                                                                                                                                                                          Ментальная модель: API contract — это письменный договор между командами (или между тобой сегодняшним и тобой через месяц), а не подразумеваемое соглашение в голове. Если backend меняет форму ошибки без предупреждения, frontend ломается тихо — вот почему OpenAPI-схема и типизированные ошибки экономят часы интеграционной отладки. В реальных компаниях frontend и backend часто пишут разные люди или разные команды, и контракт — единственное, что синхронизирует их работу без созвонов на каждый чих.

                                                                                                                                                                          +

                                                                                                                                                                          Конкретный пример: если API возвращает { error: "Not found" } в одном endpoint и { message: "Not found", code: 404 } в другом, frontend не может написать один универсальный error handler — придётся городить if-ветки под каждый случай, что быстро превращается в технический долг. Частое заблуждение junior-разработчиков — «раз fetch не выбросил exception, значит всё ок» — но fetch не бросает ошибку на HTTP 404/500, только на сетевой сбой, поэтому проверка res.ok обязательна перед res.json(), иначе распарсишь HTML-страницу ошибки как JSON и получишь непонятный краш. Три состояния — loading/error/empty, которые ты добавляешь сегодня на каждую страницу, станут обязательным критерием приёмки для Dashboard и Tasks в DevHub capstone (неделя 22, день 150) — привычка, заложенная сейчас, там уже не потребует отдельного обдумывания.

                                                                                                                                                                          +

                                                                                                                                                                          Для продакшена единый services/api.ts даёт ещё один практический бонус — единую точку для будущих улучшений вроде retry с exponential backoff или отмены запроса при размонтировании компонента (AbortController). Если fetch-логика раскидана по компонентам, добавление такой функциональности требует правки в десятке мест и почти гарантированно приводит к рассинхронизации поведения между страницами.

                                                                                                                                                                          Читать:

                                                                                                                                                                          • OpenAPI
                                                                                                                                                                          • @@ -111,7 +117,7 @@

                                                                                                                                                                            Практика (лайт / MVP)

                                                                                                                                                                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                            Если застрял

                                                                                                                                                                            -

                                                                                                                                                                            Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                            +

                                                                                                                                                                            Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                            Git

                                                                                                                                                                            • Закоммить изменения дня: git add week-21/git commit -m "week 21 day 142: API client loading error states"
                                                                                                                                                                            • @@ -124,14 +130,17 @@

                                                                                                                                                                              Ловушки


                                                                                                                                                                              День 143 (Ср): Docker — основы

                                                                                                                                                                              -

                                                                                                                                                                              Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                              -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                              +

                                                                                                                                                                              Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                              +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                              Связь с проектом: шаг к Task Manager Docker

                                                                                                                                                                              Теория

                                                                                                                                                                              Docker упаковывает приложение с зависимостями в воспроизводимый образ. Image — неизменяемый шаблон (слои); container — запущенный экземпляр. Dockerfile: FROM node:20-alpine, WORKDIR, COPY package*.json, RUN npm ci, COPY ., EXPOSE, CMD. Layer caching: сначала зависимости, потом код — быстрее rebuild.

                                                                                                                                                                              .dockerignore исключает node_modules, .git, .env из build context. docker build -t task-api . и docker run -p 3000:3000 --env-file .env task-api. Multi-stage builds (обзор): build stage + slim runtime. curl localhost:3000/api/health с хоста проверяет container.

                                                                                                                                                                              Не копируй весь проект до npm ci — инвалидируешь cache. Root user в container — для prod consider non-root (обзор). Документируй docker commands в README.

                                                                                                                                                                              +

                                                                                                                                                                              Ментальная модель: Dockerfile — рецепт, image — испечённый и замороженный пирог по рецепту, container — кусок этого пирога у тебя на тарелке прямо сейчас, который можно есть (запускать), выбросить и отрезать заново. Слои Dockerfile кешируются построчно сверху вниз, поэтому порядок инструкций — это оптимизация скорости сборки, а не просто стиль. Для junior-разработчика Docker — это уже не «плюс», а базовое требование в большинстве вакансий 2026 года: почти любая современная инфраструктура (Kubernetes, ECS, Render, Railway) ожидает готовый Docker image.

                                                                                                                                                                              +

                                                                                                                                                                              Конкретный пример цены ошибки: если скопировать весь проект (COPY . .) до npm ci, то любое изменение в исходном коде инвалидирует кеш зависимостей — пересборка занимает минуты вместо секунд при каждом маленьком изменении кода. Частое заблуждение новичков — «Docker — это как виртуальная машина» — на деле контейнеры используют namespaces и cgroups ядра хоста, а не эмулируют железо, поэтому стартуют за миллисекунды, а не минуты, и делят ядро ОС с хостом. Dockerfile для backend, который ты пишешь сегодня, станет первым сервисом в docker-compose.yml (день 145), а затем — основой Docker-инфраструктуры DevHub capstone (неделя 22, день 152), где та же логика слоёв применится уже к production-сборке.

                                                                                                                                                                              +

                                                                                                                                                                              Для продакшена размер образа тоже имеет значение: node:20-alpine весит десятки мегабайт против сотен у полного node:20, а меньший образ быстрее скачивается при деплое и содержит меньше поверхности для атак (меньше системных пакетов — меньше потенциальных CVE). Привычка сразу выбирать slim/alpine базовые образы, а не «full», экономит время и деньги на облачном биллинге по трафику и storage в масштабе реальной инфраструктуры.

                                                                                                                                                                              Читать:

                                                                                                                                                                              • Docker Overview
                                                                                                                                                                              • @@ -162,7 +171,7 @@

                                                                                                                                                                                Практика (лайт / MVP)

                                                                                                                                                                                Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                Если застрял

                                                                                                                                                                                -

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

                                                                                                                                                                                +

                                                                                                                                                                                Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                Git

                                                                                                                                                                                • Закоммить изменения дня: git add week-21/git commit -m "week 21 day 143: backend Dockerfile"
                                                                                                                                                                                • @@ -175,14 +184,17 @@

                                                                                                                                                                                  Ловушки


                                                                                                                                                                                  День 144 (Чт): Docker для frontend и PostgreSQL

                                                                                                                                                                                  -

                                                                                                                                                                                  Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                  -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                  +

                                                                                                                                                                                  Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                  +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                  Связь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                  Теория

                                                                                                                                                                                  Production frontend в Docker — multi-stage: stage 1 npm run build (Node), stage 2 nginx:alpine копирует dist/. nginx отдаёт static assets с gzip; try_files $uri /index.html — SPA fallback для client-side routes. VITE_API_URL — build-time: пересобирай image при смене API URL.

                                                                                                                                                                                  Official postgres:16 image: env POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB. Named volume pgdata:/var/lib/postgresql/data — данные переживают docker rm. localhost внутри container — сам container, не host machine; в compose network используй имя service db.

                                                                                                                                                                                  Подними три container вручную перед compose: frontend :80, API :3000, PG :5432. Backend подключается к postgres по hostname db в docker network. Проверь полный flow до docker compose.

                                                                                                                                                                                  +

                                                                                                                                                                                  Ментальная модель: named volume — это внешний жёсткий диск, который ты подключаешь к контейнеру; сам контейнер — расходный, а volume переживает docker rm и пересоздание контейнера. Путаница «localhost внутри контейнера = localhost на хосте» — одна из самых частых ошибок новичков в Docker: у каждого контейнера своя сетевая изоляция, и «localhost» там означает сам контейнер, а не машину разработчика. В production-командах эта путаница стоит часов отладки connection refused, поэтому понимание docker network — маркер зрелости junior DevOps-навыков.

                                                                                                                                                                                  +

                                                                                                                                                                                  Конкретный пример: если backend в контейнере пытается подключиться к Postgres по localhost:5432, он получит connection refused, даже если Postgres реально запущен и слушает порт — потому что это два разных сетевых namespace; правильный hostname — имя service (db) в общей docker-сети. Частое заблуждение — «раз я указал -p 5432:5432, значит порт открыт для всех контейнеров» — port mapping открывает порт наружу на хост-машину, а между контейнерами используется внутренняя docker network с DNS по именам сервисов. Multi-stage сборка frontend (build + nginx), которую ты делаешь сегодня, и правильное именование сервисов — прямая подготовка к docker-compose.yml завтрашнего дня и к продовому образу DevHub capstone.

                                                                                                                                                                                  +

                                                                                                                                                                                  Для продакшена nginx как раздатчик статики — не случайный выбор: он эффективнее Node.js-сервера для отдачи файлов благодаря event-driven архитектуре, умеет gzip/brotli-сжатие «из коробки» и не тратит ресурсы на интерпретацию JavaScript ради банальной раздачи HTML/CSS/JS. try_files $uri /index.html решает специфичную для SPA проблему: без этой директивы прямой заход на /tasks (не через клик в приложении) вернёт 404, потому что физического файла /tasks на диске не существует — весь роутинг живёт в JS-бандле.

                                                                                                                                                                                  Читать:

                                                                                                                                                                                  • nginx docker
                                                                                                                                                                                  • @@ -213,7 +225,7 @@

                                                                                                                                                                                    Практика (лайт / MVP)

                                                                                                                                                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                    Если застрял

                                                                                                                                                                                    -

                                                                                                                                                                                    Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                    +

                                                                                                                                                                                    Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                                                                                                    Git

                                                                                                                                                                                    • Закоммить изменения дня: git add week-21/git commit -m "week 21 day 144: frontend nginx and postgres containers"
                                                                                                                                                                                    • @@ -226,14 +238,17 @@

                                                                                                                                                                                      Ловушки


                                                                                                                                                                                      День 145 (Пт): docker-compose — multi-service

                                                                                                                                                                                      -

                                                                                                                                                                                      Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                      -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                      +

                                                                                                                                                                                      Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                      +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                      Связь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                      Теория

                                                                                                                                                                                      docker-compose оркестрирует multi-service приложение одним файлом. Services: db, backend, frontend; networks связывают их; volumes persist data. depends_on задаёт порядок старта, но не готовность БД — добавь healthcheck pg_isready и condition: service_healthy.

                                                                                                                                                                                      DATABASE_URL=postgresql://user:pass@db:5432/tasks — hostname db из имени service. docker compose up --build — одна команда для всего стека. docker compose down -v удаляет volumes — осторожно, потеряешь данные. Seed в entrypoint или init service.

                                                                                                                                                                                      Smoke test: open frontend → login → create task → refresh → persists. Healthchecks на db и /api/health на backend — обязательны для надёжного старта. Эта структура monorepo — прямой задел для DevHub capstone.

                                                                                                                                                                                      +

                                                                                                                                                                                      Ментальная модель: docker-compose.yml — это партитура для оркестра из нескольких контейнеров, где каждый service — отдельный музыкант, а networks и volumes — то, что позволяет им играть вместе и не терять данные между выступлениями. depends_on говорит Docker только порядок запуска процессов, а не готовность приложения внутри — Postgres-контейнер стартует за миллисекунды, но самому PostgreSQL нужны секунды на инициализацию, поэтому без healthcheck backend может упасть с connection refused при первом старте.

                                                                                                                                                                                      +

                                                                                                                                                                                      Конкретный пример: condition: service_healthy вместе с pg_isready в healthcheck заставляет Docker дождаться реальной готовности БД принимать соединения, а не просто факта, что контейнер запущен — это разница между «процесс существует» и «процесс готов работать», критичная для надёжного docker compose up без ручных перезапусков. Частое заблуждение — «docker compose down безопасен всегда» — но флаг -v удаляет volumes вместе с данными, и разработчики теряли демо-данные перед показом проекта именно так. Инфраструктура из трёх сервисов с healthcheck, которую ты собираешь сегодня, — это практически готовый docker-compose.yml для DevHub capstone (неделя 22, день 152), где добавится только auth layer и production-нюансы.

                                                                                                                                                                                      +

                                                                                                                                                                                      Для продакшена важно понимать разницу между healthcheck и readiness: даже здоровый (healthy) контейнер может быть временно не готов принимать нагрузку (например, прогревает кеш) — в managed-оркестраторах вроде Kubernetes это два разных сигнала (liveness/readiness probes), но идея та же самая, что и в compose healthcheck: не отправляй трафик туда, где сервис формально жив, но фактически ещё не готов отвечать корректно. Эта идея пригодится и за пределами Docker — в любой системе с несколькими зависимыми сервисами.

                                                                                                                                                                                      Читать:

                                                                                                                                                                                      • Compose file reference
                                                                                                                                                                                      • @@ -279,14 +294,17 @@

                                                                                                                                                                                        Ловушки


                                                                                                                                                                                        День 146 (Сб): Dev vs Prod конфигурация

                                                                                                                                                                                        -

                                                                                                                                                                                        Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                        -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                        +

                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                        +Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                        Связь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                        Теория

                                                                                                                                                                                        12 Factor App: config в environment, dev/prod parity, disposability (containers стартуют быстро). docker-compose.override.yml автоматически мержится в dev; docker-compose.prod.yml — explicit -f для production-like local. Dev: volume mount source + nodemon/uvicorn --reload; prod: optimized image без mounts.

                                                                                                                                                                                        Логи: docker compose logs -f backend. Secrets в prod — Docker secrets или cloud env, не plain text в compose file. Entrypoint script: wait-for-db → migrate → seed → start server — решает race condition при старте.

                                                                                                                                                                                        Документируй порты и команды: dev docker compose up vs prod docker compose -f docker-compose.prod.yml up. Dev volume mount может перезаписать node_modules в container — используй named volume для node_modules (обзор). Default passwords только для local.

                                                                                                                                                                                        +

                                                                                                                                                                                        Ментальная модель 12 Factor App: конфигурация должна жить в environment variables, а не в коде — тот же image должен уметь запускаться и в dev, и в staging, и в проде, отличаясь только переменными окружения снаружи. Dev/prod parity — принцип, по которому окружения должны быть максимально похожи, чтобы баг «работает у меня, не работает в проде» случался как можно реже. Для junior-разработчика эта дисциплина — то, что отличает pet-проект от продакшен-готового кода: собеседующие часто спрашивают именно про разделение dev/prod конфигурации.

                                                                                                                                                                                        +

                                                                                                                                                                                        Конкретный пример проблемы: volume mount исходников в dev-режиме (-v ./backend:/app) может незаметно перезаписать node_modules внутри контейнера локальной версией с хоста, если не выделить отдельный named volume под node_modules — итог: контейнер падает с «module not found», хотя на хосте всё установлено. Частое заблуждение — «дефолтные пароли postgres в compose-файле не проблема, это же локально» — но такие compose-файлы часто копируют в staging без изменений, и default password утекает в реальную инфраструктуру. Entrypoint-скрипт wait-for-db → migrate → seed, который ты пишешь сегодня, решает ту же race condition, что встретится в проде DevHub capstone при первом деплое (неделя 22, день 154) — паттерн одинаков в любом окружении.

                                                                                                                                                                                        +

                                                                                                                                                                                        Для продакшена явное разделение dev/prod compose файлов вместо одного «универсального» с кучей if-подобных условий — это разница между конфигурацией, которую можно быстро прочитать и понять, и конфигурацией, требующей мысленно эмулировать все возможные комбинации флагов. Команды, где такое разделение принято с самого начала, тратят заметно меньше времени на «почему в проде включился dev-режим» — классический класс инцидентов из-за спутанной конфигурации.

                                                                                                                                                                                        Читать:

                                                                                                                                                                                        • 12 Factor App
                                                                                                                                                                                        • @@ -317,7 +335,7 @@

                                                                                                                                                                                          Практика (лайт / MVP)

                                                                                                                                                                                          Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                          Если застрял

                                                                                                                                                                                          -

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

                                                                                                                                                                                          +

                                                                                                                                                                                          Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                          Git

                                                                                                                                                                                          • Закоммить изменения дня: git add week-21/git commit -m "week 21 day 146: dev prod compose configs"
                                                                                                                                                                                          • @@ -330,14 +348,17 @@

                                                                                                                                                                                            Ловушки


                                                                                                                                                                                            День 147 (Вс): E2E smoke test и ревью архитектуры

                                                                                                                                                                                            -

                                                                                                                                                                                            Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                            -Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                            +

                                                                                                                                                                                            Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                            +Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                            Связь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                            Теория

                                                                                                                                                                                            Smoke test — минимальный путь пользователя, не полный E2E suite. SMOKE_TEST.md: compose up → open app → login → CRUD task → refresh → data persists. Health endpoints нужны orchestration (Kubernetes, Render, compose healthcheck). Architecture diagram (Mermaid): client → API → DB → volumes.

                                                                                                                                                                                            Замерь cold start docker compose up --build — free tier deploy может иметь 30–60 сек warm-up; документируй в README. Сравни week-21 с требованиями DevHub capstone — список gaps в notes/capstone-prep.md. Все env vars в .env.example.

                                                                                                                                                                                            Неделя 21 — мост к финалу: та же структура frontend/ + backend/ + docker-compose.yml. Тег week-21-done. Если smoke test проходит — ты готов к DevHub.

                                                                                                                                                                                            +

                                                                                                                                                                                            Ментальная модель: smoke test — это не полный regression suite, а быстрая проверка «дым идёт, значит мотор хотя бы завёлся» — минимальный путь, который ловит catastrophic failures за минуту вместо часа полного прогона тестов. Architecture diagram решает другую задачу — она переводит код в общий язык для ревьюера, коллеги или будущего тебя, который забыл детали через полгода. Для junior-разработчика умение за 2 минуты нарисовать архитектуру своего проекта на созвоне — практический навык, который прямо оценивают на техническом интервью.

                                                                                                                                                                                            +

                                                                                                                                                                                            Конкретный пример: если docker compose up --build первый раз занимает 45 секунд из-за скачивания base images и сборки, а команда об этом не знает, они решат, что деплой завис, и начнут паниковать — задокументированный cold start снимает эту неопределённость. Частое заблуждение — «раз у меня всё работает локально, значит и в capstone заработает» — но сравнение чек-листа week-21 с требованиями DevHub (список gaps в notes/capstone-prep.md) именно для того и нужно, чтобы найти пробелы заранее, а не в последний день недели 22, когда времени на исправление уже не будет. Mermaid-диаграмма и smoke-checklist, которые ты создаёшь сегодня, станут прямыми шаблонами для ARCHITECTURE.md и SMOKE_TEST.md капстоуна.

                                                                                                                                                                                            +

                                                                                                                                                                                            Для продакшена регулярный smoke test — это то, что команды запускают сразу после каждого деплоя, ещё до того как объявить релиз завершённым: если базовый путь пользователя (login → основное действие → выход) не работает, откатывать деплой нужно немедленно, не дожидаясь жалоб реальных пользователей. Привычка писать такой чек-лист за 10 минут до того, как считать задачу «готовой», экономит часы разбора инцидентов в проде.

                                                                                                                                                                                            Читать:

                                                                                                                                                                                            • DevHub Capstone spec
                                                                                                                                                                                            • @@ -368,7 +389,7 @@

                                                                                                                                                                                              Практика (лайт / MVP)

                                                                                                                                                                                              Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                              Если застрял

                                                                                                                                                                                              -

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

                                                                                                                                                                                              +

                                                                                                                                                                                              Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                              Git

                                                                                                                                                                                              • Закоммить изменения дня: git add week-21/git commit -m "week 21 day 147: smoke test and architecture diagram"
                                                                                                                                                                                              • diff --git a/docs/w/22.html b/docs/w/22.html index f30f61a..d0d133a 100644 --- a/docs/w/22.html +++ b/docs/w/22.html @@ -24,14 +24,17 @@

                                                                                                                                                                                                День 148 (Пн): Планирование DevHub Capstone

                                                                                                                                                                                                -

                                                                                                                                                                                                Время (полный): ~1ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                +

                                                                                                                                                                                                Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                Связь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                Теория

                                                                                                                                                                                                DevHub Capstone — синтез 22 недель обучения. Не начинай код в последний день: день 148 — планирование, 149–153 — реализация, 154 — deploy и портфолио. Прочитай полную спецификацию в projects.md: концепция (дашборд + заметки + задачи + GitHub API), обязательный стек, MVP vs nice-to-have.

                                                                                                                                                                                                Scope control критичен: 7 дней, фиксированный MVP из 9 пунктов. WebSocket, kanban drag-and-drop, chat — после MVP. User stories формата «As a developer, I want…» с acceptance criteria превращают размытые идеи в проверяемые задачи.

                                                                                                                                                                                                Структура repo: frontend/, backend/, docker-compose.yml, .github/workflows/ci.yml. Выбери один backend: FastAPI (нед. 18) или Express (нед. 19). ER-диаграмма ≥ 5 сущностей, API endpoints list, page map React — артефакты до первой строки кода. Скопируй структуру week-21 как стартовую точку.

                                                                                                                                                                                                +

                                                                                                                                                                                                Ментальная модель: планирование — это карта перед походом, а не бюрократия, отнимающая время от «настоящей» работы. Час, потраченный на PLAN.md и ER-диаграмму, экономит часы блуждания в коде посреди недели, когда неясно, зачем нужна ещё одна таблица или откуда взялся баг в связях данных. Для junior-разработчика умение декомпозировать нечёткое задание («сделай платформу разработчика») на конкретные user stories с acceptance criteria — один из самых ценных навыков, который отличает исполнителя от инженера, способного работать самостоятельно.

                                                                                                                                                                                                +

                                                                                                                                                                                                Конкретный пример цены отсутствия плана: команды, которые прыгают в код без ER-диаграммы, типично обнаруживают на четвёртый день, что забыли связь many-to-many между notes и tags, и переделывают миграции задним числом, теряя данные тестового прогона. Частое заблуждение — «за 7 дней успею и kanban с drag-and-drop, и WebSocket-чат, и weather widget» — это классический scope creep, который гарантированно оставляет MVP недоделанным; профессиональные команды сначала фиксируют MVP, а «хотелки» уходят в backlog. Артефакты сегодняшнего дня — PLAN.md, ER-диаграмма, page map — не формальность для галочки, а рабочие документы, на которые ты будешь ссылаться каждый день оставшейся недели.

                                                                                                                                                                                                +

                                                                                                                                                                                                Для продакшена этот же принцип масштабируется на уровень целых команд: перед стартом крупной фичи инженерные команды пишут design doc или RFC именно по той же причине — зафиксировать scope и получить обратную связь до того, как написана первая строка кода, а не после недели работы впустую. Умение написать короткий, но конкретный план — навык, который пригодится далеко за пределами этого одного проекта.

                                                                                                                                                                                                Читать:

                                                                                                                                                                                                • DevHub Capstone
                                                                                                                                                                                                • @@ -79,14 +82,17 @@

                                                                                                                                                                                                  Ловушки


                                                                                                                                                                                                  День 149 (Вт): Backend DevHub

                                                                                                                                                                                                  -

                                                                                                                                                                                                  Время (полный): ~1ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                  -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                  +

                                                                                                                                                                                                  Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                  +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                  Связь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                  Теория

                                                                                                                                                                                                  Backend DevHub — layered API: routers → services → repositories → PostgreSQL. Переиспользуй паттерны Library REST API (нед. 18) или Express Notes (нед. 19): APIRouter/Express Router, Pydantic/Zod validation, пагинация { items, total, page, size }, OpenAPI/Swagger.

                                                                                                                                                                                                  Схема БД: users, tasks, notes, tags, note_tags — минимум 5 сущностей со связями. CRUD tasks с user_id FK; notes с markdown body и тегами many-to-many. GET /api/v1/dashboard/stats — агрегаты для виджетов. Пока без auth — заглушка user_id, auth на день 151.

                                                                                                                                                                                                  Миграции: Alembic (FastAPI) или SQL scripts (Express). Seed: demo user + sample data для демо и тестов. .env.example: DATABASE_URL, JWT_SECRET, APP_ENV. God router на 500 строк — разбей по доменам. Пагинация с первого дня — иначе сломается на реальных данных.

                                                                                                                                                                                                  +

                                                                                                                                                                                                  Ментальная модель: layered architecture (routers → services → repositories) — это как конвейер: каждый слой отвечает за одну зону ответственности, и изменение в одной зоне (например, смена ORM) не требует переписывать HTTP-обработчики. Для junior backend-разработчика способность структурировать API не «одним файлом на 2000 строк», а по доменам — прямой признак, который ревьюер видит за первые пять минут просмотра репозитория на собеседовании или в портфолио.

                                                                                                                                                                                                  +

                                                                                                                                                                                                  Конкретный пример: GET /api/v1/dashboard/stats выглядит как простой endpoint, но требует агрегации из нескольких таблиц (count tasks by status, recent notes) — если логику агрегации не вынести в отдельный service, она расползётся дублированием в разных местах роутера при добавлении новых виджетов. Частое заблуждение — «auth — это скучная обвязка, сделаю CRUD, а потом уже security» — на самом деле откладывание auth на день 151 осознанно: это позволяет сосредоточиться на форме данных сегодня, но заглушка user_id должна быть явной и задокументированной, а не забытой лазейкой. Сегодняшняя схема БД (users, tasks, notes, tags, note_tags) — это тот самый набор ≥5 сущностей, который прямо проверяется в критериях сдачи capstone, поэтому качество миграций и seed данных сейчас определяет, насколько гладко пройдёт остаток недели.

                                                                                                                                                                                                  +

                                                                                                                                                                                                  Для продакшена OpenAPI/Swagger документация, которую генерирует FastAPI автоматически (или которую нужно написать вручную для Express), — это не просто «красивая страница», а контракт, на который будет опираться frontend-разработчик (день 150) при написании типов; расхождение между реальным API и документацией — источник багов интеграции, которые сложно диагностировать без явного сравнения запроса и ответа.

                                                                                                                                                                                                  Читать:

                                                                                                                                                                                                  • Library REST API (нед. 18)
                                                                                                                                                                                                  • @@ -121,7 +127,7 @@

                                                                                                                                                                                                    Практика (лайт / MVP)

                                                                                                                                                                                                    Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                    Если застрял

                                                                                                                                                                                                    -

                                                                                                                                                                                                    Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                    +

                                                                                                                                                                                                    Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                    Git

                                                                                                                                                                                                    • Закоммить изменения дня: git add week-22-capstone/backend/git commit -m "week 22 day 149: DevHub backend models and CRUD API"
                                                                                                                                                                                                    • @@ -134,14 +140,17 @@

                                                                                                                                                                                                      Ловушки


                                                                                                                                                                                                      День 150 (Ср): Frontend DevHub (React + TypeScript)

                                                                                                                                                                                                      -

                                                                                                                                                                                                      Время (полный): ~1ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                      -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                      +

                                                                                                                                                                                                      Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                      +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                      Связь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                      Теория

                                                                                                                                                                                                      Frontend DevHub собирает навыки Portfolio SPA (нед. 13) и React Dashboard (нед. 14). React 18+ TypeScript, React Router, Context или Zustand для глобального state. Структура: pages/, components/, hooks/, services/api.ts, types/. VITE_API_URL — base URL API.

                                                                                                                                                                                                      Четыре+ маршрута с Layout: /dashboard, /tasks, /notes, /profile. Shared UI kit: Button, Card, Spinner, ErrorMessage — консистентность. Loading / error / empty на каждой data-fetching странице — не «потом». Mobile-first layout для dashboard.

                                                                                                                                                                                                      services/api.ts — typed fetch wrapper; не fetch в каждом компоненте. Tasks: CRUD, фильтр status/priority. Notes: markdown textarea + preview, теги. Dashboard: виджеты статистики, placeholder GitHub repos. TypeScript strict, без any в api layer. Auth подключишь на день 151.

                                                                                                                                                                                                      +

                                                                                                                                                                                                      Ментальная модель: frontend capstone — это не новый набор навыков, а синтез уже отработанных паттернов (Portfolio SPA, React Dashboard) в одном большом приложении — организация pages/hooks/services/types масштабирует то, что раньше умещалось в пару файлов. Для junior frontend-роли способность держать типизацию строгой (TypeScript strict, без any в api layer) на растущем проекте — именно то, что отличает код, готовый к сопровождению командой, от одноразового прототипа.

                                                                                                                                                                                                      +

                                                                                                                                                                                                      Конкретный пример: без shared UI kit (Button, Card, Spinner, ErrorMessage) четыре страницы (dashboard, tasks, notes, profile) неизбежно разъедутся визуально — один разработчик сделает spinner в виде текста «Loading...», другой — CSS-анимацию, и продукт будет выглядеть несобранным, даже если код работает. Частое заблуждение — «auth подключу позже, сейчас не важно» — верно для порядка работы, но опасно, если забыть спроектировать api.ts так, чтобы Bearer-заголовок можно было добавить одной строкой на день 151, а не переписывать весь fetch-слой заново. Четыре маршрута с общим Layout, которые ты собираешь сегодня, — это тот самый page map, который завтра обрастёт защищёнными маршрутами, а через несколько дней — Docker-инфраструктурой для деплоя.

                                                                                                                                                                                                      +

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

                                                                                                                                                                                                      Читать:

                                                                                                                                                                                                      • React Dashboard (нед. 14)
                                                                                                                                                                                                      • @@ -176,7 +185,7 @@

                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                        -

                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                        +

                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                        Git

                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/frontend/git commit -m "week 22 day 150: DevHub React TS pages and API client"
                                                                                                                                                                                                        • @@ -189,14 +198,17 @@

                                                                                                                                                                                                          Ловушки


                                                                                                                                                                                                          День 151 (Чт): Auth — JWT end-to-end

                                                                                                                                                                                                          -

                                                                                                                                                                                                          Время (полный): ~55м теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                          -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                          +

                                                                                                                                                                                                          Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                          +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                          Связь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                          Теория

                                                                                                                                                                                                          Auth end-to-end — обязательный MVP пункт. Переиспользуй Secure Notes (нед. 20): bcrypt/passlib, JWT, middleware на protected routes. Backend: POST /auth/register, POST /auth/login; все /api/v1/* требуют Authorization: Bearer. user_id из JWT payload — не из request body (IDOR уязвимость).

                                                                                                                                                                                                          Frontend: AuthProvider, useAuth(), /login, /register, protected routes с redirect. api.ts — auto Bearer header, logout on 401. Rate limit на login, CORS whitelist, helmet — из недели 20. Начни SECURITY.md с OWASP checklist.

                                                                                                                                                                                                          E2E manual test: register → login → create task → logout → login → task visible. User A не видит данные User B → 403. JWT secret в git — rotate немедленно. Задокументируй выбор localStorage vs httpOnly cookie.

                                                                                                                                                                                                          +

                                                                                                                                                                                                          Ментальная модель: auth в capstone — не отдельная фича, а сквозной слой, который пронизывает буквально каждый существующий endpoint и компонент — именно поэтому его добавляют после того, как CRUD уже работает, а не в начале, чтобы не отлаживать две сложные вещи одновременно. Для нанимающего junior full-stack инженера способность интегрировать auth end-to-end в уже существующую кодовую базу без переписывания архитектуры с нуля — куда более реалистичный сценарий работы, чем стартовать проект «с чистого листа».

                                                                                                                                                                                                          +

                                                                                                                                                                                                          Конкретный пример риска: если миграция привязки tasks/notes к user_id сделана небрежно (например, дефолтное значение user_id = 1 для старых записей), в проде это создаст ситуацию, где новый пользователь внезапно видит демо-данные предыдущего — классическая ошибка, которую тестовый прогон «user A не видит данные user B» обязан поймать. Частое заблуждение — «раз я использую JWT, IDOR мне не грозит» — сам факт наличия токена не защищает, если backend всё равно читает user_id из тела запроса вместо payload токена; уязвимость возникает именно в этой конкретной строчке кода, а не в отсутствии JWT вообще. Auth end-to-end, который ты собираешь сегодня, — последний функциональный кирпич MVP перед инфраструктурными днями (Docker, тесты, деплой), поэтому качество этого дня определяет, будет ли остаток недели про полировку или про латание дыр в безопасности.

                                                                                                                                                                                                          +

                                                                                                                                                                                                          Для продакшена стоит помнить: SECURITY.md, который ты начинаешь сегодня, — живой документ, а не разовый чеклист. В реальных компаниях подобные документы обновляются при каждом security review и служат доказательством due diligence перед аудиторами или партнёрами — привычка вести такую документацию с первого капстоун-проекта переносится в профессиональную практику без переучивания.

                                                                                                                                                                                                          Читать:

                                                                                                                                                                                                          • Secure Notes (нед. 20)
                                                                                                                                                                                                          • @@ -231,7 +243,7 @@

                                                                                                                                                                                                            Практика (лайт / MVP)

                                                                                                                                                                                                            Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                            Если застрял

                                                                                                                                                                                                            -

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

                                                                                                                                                                                                            +

                                                                                                                                                                                                            Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                            Git

                                                                                                                                                                                                            • Закоммить изменения дня: git add week-22-capstone/git commit -m "week 22 day 151: DevHub JWT auth frontend backend"
                                                                                                                                                                                                            • @@ -244,14 +256,17 @@

                                                                                                                                                                                                              Ловушки


                                                                                                                                                                                                              День 152 (Пт): Docker — локальный full-stack

                                                                                                                                                                                                              -

                                                                                                                                                                                                              Время (полный): ~55м теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                              -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                              +

                                                                                                                                                                                                              Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                              +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                              Связь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                              Теория

                                                                                                                                                                                                              Docker Compose — критерий сдачи capstone: docker compose up поднимает всё локально. Переиспользуй Task Manager Docker (нед. 21): services db, backend, frontend; healthchecks; named volumes; entrypoint wait-for-db → migrate → seed → start.

                                                                                                                                                                                                              Multi-stage frontend Dockerfile (nginx + dist). Backend Dockerfile slim. VITE_API_URL как build arg — в docker network указывает на backend service, не localhost. .dockerignore в обоих папках. ARCHITECTURE.md с Mermaid: client → API → DB → volumes.

                                                                                                                                                                                                              README «запуск за 5 команд»: clone → copy .envdocker compose up --build → open browser. Backend стартует до PG — healthcheck + retry в entrypoint. Полный smoke: auth + CRUD через dockerized frontend.

                                                                                                                                                                                                              +

                                                                                                                                                                                                              Ментальная модель: docker compose up для целого capstone — это финальная репетиция перед premiere: если что-то не заводится в контейнерах, лучше узнать это сегодня, а не в день деплоя, когда времени на диагностику почти не останется. Для оценки готовности к junior-позиции воспроизводимость окружения («работает не только у меня») — один из первых критериев, которые технический ревьюер портфолио проверяет буквально за одну команду docker compose up --build.

                                                                                                                                                                                                              +

                                                                                                                                                                                                              Конкретный пример: VITE_API_URL — build-time переменная, поэтому её нельзя просто передать в docker run как runtime env — если её значение зашито на localhost во время npm run build внутри Docker, production-сборка frontend будет пытаться достучаться до localhost из браузера пользователя, а не до реального backend, и все запросы будут падать молча. Частое заблуждение — «раз локально все три сервиса работают по отдельности, вместе тоже заработают» — но именно network-конфигурация (hostname backend вместо localhost, healthcheck на PostgreSQL) чаще всего ломается при первой сборке compose-стека. ARCHITECTURE.md с Mermaid-диаграммой, который ты создаёшь сегодня, станет частью финального README и будет тем документом, который ревьюер или интервьюер откроет первым, чтобы за 30 секунд понять устройство твоего DevHub.

                                                                                                                                                                                                              +

                                                                                                                                                                                                              Для продакшена «запуск за 5 команд» в README — это не про красоту, а про снижение барьера для onboarding: чем больше шагов и недокументированных предположений («у тебя же уже установлен Postgres 16, да?») требует локальный запуск, тем меньше шанс, что коллега, ревьюер или рекрутер вообще дойдут до того, чтобы попробовать проект — большинство просто закроют вкладку после первой непонятной ошибки.

                                                                                                                                                                                                              Читать:

                                                                                                                                                                                                              • Task Manager Docker (нед. 21)
                                                                                                                                                                                                              • @@ -299,14 +314,17 @@

                                                                                                                                                                                                                Ловушки


                                                                                                                                                                                                                День 153 (Сб): Тесты и CI

                                                                                                                                                                                                                -

                                                                                                                                                                                                                Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                +

                                                                                                                                                                                                                Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                Связь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                Теория

                                                                                                                                                                                                                Quality gate capstone: pytest ≥ 15, Vitest ≥ 12, ESLint без ошибок, CI green on push. Тесты из MVP: auth flow, CRUD tasks, 401 без token, 403 cross-user. GitHub Actions: job backend (postgres service + pytest) + job frontend (vitest + lint). Badge CI в README.

                                                                                                                                                                                                                Test DB isolation — postgres service в CI или SQLite in-memory; не production. Flaky tests из shared state — изолируй fixtures с rollback. npm audit / pip audit — зафиксируй в SECURITY.md. Auth flow должен быть покрыт тестами, не только manual E2E.

                                                                                                                                                                                                                Локально все тесты зелёные перед push. CI без postgres service — тесты падают на GitHub. Это последний рубеж перед deploy: если CI красный, deploy откладывается.

                                                                                                                                                                                                                +

                                                                                                                                                                                                                Ментальная модель: quality gate — это шлагбаум, который физически не пускает недоделанный код дальше, а не вежливая рекомендация. Тесты на auth flow и cross-user isolation (403) — не для галочки количества, а потому что именно эти сценарии чаще всего ломаются при рефакторинге и именно они наносят максимальный репутационный ущерб, если баг просочится в прод. Для junior-кандидата зелёный CI badge на GitHub рядом с ≥15 backend и ≥12 frontend тестами — конкретное, проверяемое доказательство инженерной дисциплины, которое весит больше любых слов в резюме.

                                                                                                                                                                                                                +

                                                                                                                                                                                                                Конкретный пример: postgres service в GitHub Actions должен быть объявлен явно в workflow — если локально тесты используют реальный Postgres, а в CI забыли добавить сервис, тесты будут падать с connection refused именно на GitHub, хотя «на моей машине всё зелёное»; это одна из самых частых причин красного CI у новичков. Частое заблуждение — «раз тесты проходят локально один раз, в CI тоже пройдут» — flaky tests из-за shared state (например, два теста создают пользователя с одинаковым email) проявляются именно в CI, где тесты могут выполняться в другом порядке или параллельно. Green CI, который ты добиваешься сегодня, — формальный шлюз перед деплоем: день 154 начинается только если этот шлагбаум поднят.

                                                                                                                                                                                                                +

                                                                                                                                                                                                                Для продакшена ESLint без ошибок — минимальная, но обязательная планка стиля: она не заменяет тесты, но ловит целый класс проблем до code review (неиспользуемые переменные, потенциальные null-referenced, несогласованный стиль) и экономит время ревьюера на комментарии вроде «убери console.log». Badge CI в README — маленькая деталь, которая на практике заметно повышает доверие к репозиторию при первом взгляде.

                                                                                                                                                                                                                Читать:

                                                                                                                                                                                                                • Quality в стеке
                                                                                                                                                                                                                • @@ -340,7 +358,7 @@

                                                                                                                                                                                                                  Практика (лайт / MVP)

                                                                                                                                                                                                                  Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                  Если застрял

                                                                                                                                                                                                                  -

                                                                                                                                                                                                                  Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                  +

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

                                                                                                                                                                                                                  Git

                                                                                                                                                                                                                  • Закоммить изменения дня: git add week-22-capstone/git commit -m "week 22 day 153: DevHub tests and GitHub Actions CI"
                                                                                                                                                                                                                  • @@ -353,14 +371,16 @@

                                                                                                                                                                                                                    Ловушки


                                                                                                                                                                                                                    День 154 (Вс): Deploy, портфолио и финальное ревью

                                                                                                                                                                                                                    -

                                                                                                                                                                                                                    Время (полный): ~1ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                    -Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                    +

                                                                                                                                                                                                                    Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                    +Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                    Связь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                    Теория

                                                                                                                                                                                                                    Финальный день — deploy, портфолио и рефлексия. Frontend → Vercel/Netlify (root frontend/, VITE_API_URL = production API). Backend + managed PostgreSQL → Render/Railway/Neon. После deploy: обнови CORS для Vercel domain, rotate JWT_SECRET если был в git, env vars в cloud dashboard.

                                                                                                                                                                                                                    Live HTTPS demo — критерий сдачи: register → login → CRUD в браузере. FINAL_REVIEW.md: что узнал за 22 недели, что бы сделал иначе. GitHub Profile README — таблица всех 22 проектов со ссылками. README DevHub: badges, demo URL, screenshots, docker setup, architecture.

                                                                                                                                                                                                                    Free tier cold start 30–60 сек — документируй. Забытый CORS update — API works in curl, fails в browser на Vercel. 2-минутный pitch DevHub — устная репетиция архитектуры. Тег week-22-done — финиш роадмапа. Поздравляем: ты junior full-stack ready.

                                                                                                                                                                                                                    +

                                                                                                                                                                                                                    Ментальная модель: деплой — это момент, когда проект перестаёт быть «у меня на компьютере» и становится реальным продуктом, доступным по HTTPS кому угодно в интернете — переход от localhost к публичному URL меняет требования к конфигурации (CORS, секреты, переменные окружения) даже если код не изменился ни на строчку. Для junior-кандидата live demo — это разница между «я утверждаю, что умею» и «вот ссылка, попробуйте сами»: ссылку на живой проект рекрутер откроет с гораздо большей вероятностью, чем будет разбираться, как поднять твой репозиторий локально.

                                                                                                                                                                                                                    +

                                                                                                                                                                                                                    Конкретный пример типичного провала: backend работает и отвечает на curl-запросы с production URL, но при заходе через браузер запросы падают с CORS error — потому что при деплое забыли добавить домен Vercel в whitelist Access-Control-Allow-Origin, который до этого содержал только localhost:5173. Частое заблуждение — «раз всё запушено и задеплоено, работа закончена» — но FINAL_REVIEW.md и обновлённый GitHub Profile README — не бюрократия, а то, что реально увидит рекрутер или технический интервьюер в первую очередь: рефлексия о пройденном пути показывает зрелость мышления не хуже самого кода. Тег week-22-done, который ты ставишь сегодня, закрывает 22-недельный путь — но именно эта финальная неделя, с её деплоем, документацией и портфолио, превращает набор учебных проектов в осязаемое доказательство готовности к первой работе full-stack разработчиком.

                                                                                                                                                                                                                    Читать:

                                                                                                                                                                                                                    • Критерии сдачи capstone
                                                                                                                                                                                                                    • @@ -399,7 +419,7 @@

                                                                                                                                                                                                                      Практика (лайт / MVP)

                                                                                                                                                                                                                      Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                      Если застрял

                                                                                                                                                                                                                      -

                                                                                                                                                                                                                      Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                      +

                                                                                                                                                                                                                      Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                      Git

                                                                                                                                                                                                                      • Закоммить изменения дня: git add week-22-capstone/git commit -m "week 22 day 154: DevHub deploy portfolio FINAL_REVIEW"
                                                                                                                                                                                                                      • diff --git a/docs/weeks/00.json b/docs/weeks/00.json index 6012326..75aabc9 100644 --- a/docs/weeks/00.json +++ b/docs/weeks/00.json @@ -1 +1 @@ -{"id": "week-00", "title": "Онбординг", "fullTitle": "Неделя 0: Онбординг — до первого HTML", "html": "

                                                                                                                                                                                                                        Неделя 0: Онбординг — до первого HTML

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель: подготовить инструменты, аккаунты и репозиторий learning-log до недели 1.\nВремя: 2–4 часа (один раз)\nПроект: инфраструктура обучения, не код недели

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Зачем отдельная неделя 0

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Неделя 1 сразу про HTML и Git. Если VS Code, Git и GitHub не готовы — первый день уйдёт на установку, а не на index.html. Неделя 0 снимает трение: среда, аккаунт, репозиторий, понимание «как учиться».

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 0.1: Инструменты

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~40м теория · ~1.5ч практика · ~10м проверка
                                                                                                                                                                                                                        \nВремя (лайт): ~20м теория · ~45м практика
                                                                                                                                                                                                                        \nСвязь с проектом: стабильная среда для всех следующих недель

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Веб-разработка начинается не с кода, а со среды: редактор, браузер с DevTools, терминал, Git. Эти инструменты останутся с вами на годы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        VS Code — редактор с встроенным терминалом и Git. Chrome DevTools — Elements (DOM/CSS), Console (ошибки JS), Network (запросы). Git — история изменений; без него нет портфолио.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: стабильная среда важнее скорости «сразу писать код».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать: Как начать — таблица инструментов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Установи VS Code, Chrome (или Chromium), Git
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. В VS Code: Live Server, GitLens, ESLint, Prettier, Error Lens
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Проверь в терминале: git --version (должен ответить версией)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Node.js LTS можно поставить сейчас или перед неделей 11; Python — перед 15; Docker — перед 21
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Открой DevTools (F12 / ⌥⌘I) → Elements, Console, Network — кликни по каждой вкладке
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. VS Code + Git + Chrome
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Live Server + одно расширение на выбор
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. git --version работает
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: редактор, браузер с DevTools и Git установлены.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Установка зависла — перезапусти установщик, проверь PATH (echo $PATH / «Переменные среды» на Windows). Git «не найден» после установки — закрой и открой терминал заново.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 0.2: GitHub и свой learning-log

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~30м теория · ~1ч практика · ~15м Git
                                                                                                                                                                                                                        \nВремя (лайт): ~15м теория · ~40м практика · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: публичное портфолио с дня 1 недели 1

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Публичный learning-log — портфолио в процессе. Рекрутер видит дисциплину: коммиты, сообщения, рост по неделям — не только финальный zip.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Репозиторий создаёте под своим аккаунтом, пустой (без README от GitHub), затем клонируете себе. Не клонируйте чужой learning-log — это должен быть ваш граф коммитов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: репозиторий появляется до первой строки HTML.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Аккаунт GitHub (если нет) + 2FA по возможности
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. New repository → имя learning-log → Public → без README / .gitignore / license
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Скопируйте URL и клонируйте:
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        git clone https://github.com/<ваш-логин>/learning-log.git\ncd learning-log\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создайте .gitignore:
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        echo -e ".DS_Store\\nThumbs.db\\n.env\\nnode_modules/\\n*.log\\n.venv/" > .gitignore\ngit add .gitignore\ngit commit -m "chore: init learning-log"\ngit push -u origin main\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создайте минимальный README.md: название, цель («прохожу web-roadmap»), ссылка на https://github.com/krwg/web-roadmap — закоммитьте
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создать пустой learning-log под своим аккаунтом
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Clone → .gitignore → первый push
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: репозиторий виден на github.com/ваш-логин/learning-log

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Permission denied / auth — используйте HTTPS + Personal Access Token или GitHub CLI (gh auth login). Ветка называется master вместо main — переименуйте: git branch -M main.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 0.3: Как учиться по маршруту

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~45м теория · ~40м практика · ~10м Git
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~25м практика
                                                                                                                                                                                                                        \nСвязь с проектом: выбрать полный или лайт-трек до недели 1

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Каждый учебный день недель 1–22:

                                                                                                                                                                                                                        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                                                                                                                                                                        БлокЗачем
                                                                                                                                                                                                                        ТеорияСвои слова + ссылки (MDN, книги). Не пропускать
                                                                                                                                                                                                                        Практика (полный)Все пункты ТЗ дня
                                                                                                                                                                                                                        Практика (лайт)MVP-подмножество, если мало времени
                                                                                                                                                                                                                        GitМинимум один осмысленный коммит
                                                                                                                                                                                                                        Если застрялПодсказка по теме дня, не копипаст
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Полный трек (~5–7 ч/день): максимум глубины. Лайт (~3–4 ч): теория + лайт-практика + Git; проект недели — в урезанном DoD из каталога.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Протокол «анти-вайбкодер»: ИИ объясняет концепцию или ревьюит ваш код. Не пишет за вас.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Введение\n- Каталог 22 проектов

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Прочитай introduction и обзор проектов
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. В learning-log создай journal.md — цель на 22 недели одним абзацем
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Открой сайт маршрута — закрепи вкладку
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Выбери трек (полный / лайт) и запиши выбор в journal
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Коммит: chore: add learning journal
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Прочитай introduction (хотя бы разделы «для кого» и «как устроен день»)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. journal.md с целью + закладка на сайт
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не знаете, полный или лайт — начните лайт на 3 дня. Если стабильно укладываетесь с запасом — переключитесь на полный со следующей недели.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Два трека нагрузки

                                                                                                                                                                                                                        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                                                                                                                                                                        ТрекЧасов/деньКогда выбирать
                                                                                                                                                                                                                        Полный~5–7Цель — junior full-stack, есть время
                                                                                                                                                                                                                        Лайт~3–4Работа/учёба параллельно; проект недели в MVP
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        В лайт-треке проект недели обязателен в урезанном виде — без него навык не склеится. Часы в днях недель 1–22 пересчитаны по объёму практики (не копипаст «1.5 + 2.5» на каждый день).

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nГотов ли я к неделе 1?\n\n- [ ] VS Code + браузер с DevTools работают\n- [ ] `learning-log` на **вашем** GitHub, есть `.gitignore` и хотя бы один коммит\n- [ ] Понимаю день: теория → практика (полный или лайт) → Git\n- [ ] Знаю, где открыть план недели на сайте\n- [ ] Выбран трек нагрузки\n\n
                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Неделя 1: HTML

                                                                                                                                                                                                                        ", "toc": [{"id": "week-00-зачем-отдельная-неделя-0", "label": "Зачем отдельная неделя 0"}, {"id": "week-00-day-0-1", "label": "День 0.1: Инструменты"}, {"id": "week-00-day-0-2", "label": "День 0.2: GitHub и свой learning-log"}, {"id": "week-00-day-0-3", "label": "День 0.3: Как учиться по маршруту"}, {"id": "week-00-два-трека-нагрузки", "label": "Два трека нагрузки"}, {"id": "week-00-review", "label": "Проверь себя"}], "text": "Неделя 0: Онбординг — до первого HTML Цель: подготовить инструменты, аккаунты и репозиторий learning-log до недели 1 . Время: 2–4 часа (один раз) Проект: инфраструктура обучения, не код недели Зачем отдельная неделя 0 Неделя 1 сразу про HTML и Git. Если VS Code, Git и GitHub не готовы — первый день уйдёт на установку, а не на index.html . Неделя 0 снимает трение: среда, аккаунт, репозиторий, понимание «как учиться». День 0.1: Инструменты Время (полный): ~40м теория · ~1.5ч практика · ~10м проверка Время (лайт): ~20м теория · ~45м практика Связь с проектом: стабильная среда для всех следующих недель Теория Веб-разработка начинается не с кода, а со среды : редактор, браузер с DevTools, терминал, Git. Эти инструменты останутся с вами на годы. VS Code — редактор с встроенным терминалом и Git. …"} \ No newline at end of file +{"id": "week-00", "title": "Онбординг", "fullTitle": "Неделя 0: Онбординг — до первого HTML", "html": "

                                                                                                                                                                                                                        Неделя 0: Онбординг — до первого HTML

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель: подготовить инструменты, аккаунты и репозиторий learning-log до недели 1.\nВремя: 2–4 часа (один раз)\nПроект: инфраструктура обучения, не код недели

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Зачем отдельная неделя 0

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Неделя 1 сразу про HTML и Git. Если VS Code, Git и GitHub не готовы — первый день уйдёт на установку, а не на index.html. Неделя 0 снимает трение: среда, аккаунт, репозиторий, понимание «как учиться».

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 0.1: Инструменты

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~40м теория · ~1.5ч практика · ~10м проверка
                                                                                                                                                                                                                        \nВремя (лайт): ~20м теория · ~45м практика
                                                                                                                                                                                                                        \nСвязь с проектом: стабильная среда для всех следующих недель

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Веб-разработка начинается не с кода, а со среды: редактор, браузер с DevTools, терминал, Git. Эти инструменты останутся с вами на годы, поэтому час, потраченный сегодня на настройку, окупится десятки раз позже.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Удобная мысленная модель: редактор — мастерская, где вы создаёте вещь; браузер с DevTools — рентген, который показывает, что получилось на самом деле; терминал — пульт, откуда команды отдаются инструментам напрямую, а не кликами мыши; Git — машина времени, которая помнит каждую версию вашей работы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        VS Code — редактор с встроенным терминалом и подсветкой Git-изменений прямо в файлах. Chrome DevTools — три вкладки на каждый день: Elements показывает живое дерево DOM и применённые CSS-правила, Console выводит ошибки JavaScript, Network — что загрузила страница и сколько это заняло. Git — история изменений; без него нет портфолио и нет пути назад, если что-то сломалось.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: через несколько недель вы случайно удалите важный кусок CSS и не заметите это сразу — git diff покажет ровно те строки, что изменились со вчерашнего коммита, и восстановить код можно за секунды вместо часа гаданий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частая ошибка новичков — писать код без Git «чтобы не тратить время на настройку», откладывая репозиторий «на потом, когда будет что показать». Тогда первые недели прогресса нигде не задокументированы. Такая же ошибка — отлаживать вёрстку методом «поменял файл — обновил страницу — посмотрел», хотя Elements с редактированием стилей на лету делает это быстрее.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: стабильная среда важнее скорости «сразу писать код» — сегодняшняя практика единственный раз в маршруте посвящена только настройке, чтобы дальше ничего не отвлекало от обучения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать: Как начать — таблица инструментов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Установи VS Code, Chrome (или Chromium), Git
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. В VS Code: Live Server, GitLens, ESLint, Prettier, Error Lens
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Проверь в терминале: git --version (должен ответить версией)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Node.js LTS можно поставить сейчас или перед неделей 11; Python — перед 15; Docker — перед 21
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Открой DevTools (F12 / ⌥⌘I) → Elements, Console, Network — кликни по каждой вкладке
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. VS Code + Git + Chrome
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Live Server + одно расширение на выбор
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. git --version работает
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: редактор, браузер с DevTools и Git установлены.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Установка зависла — перезапусти установщик, проверь PATH (echo $PATH / «Переменные среды» на Windows). Git «не найден» после установки — закрой и открой терминал заново.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 0.2: GitHub и свой learning-log

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~30м теория · ~1ч практика · ~15м Git
                                                                                                                                                                                                                        \nВремя (лайт): ~15м теория · ~40м практика · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: публичное портфолио с дня 1 недели 1

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Публичный learning-log — портфолио в процессе, а не готовая витрина. Рекрутер, который откроет ваш GitHub через полгода, видит не только финальный код, но и дисциплину: регулярные коммиты, внятные сообщения, заметный рост качества от недели 1 к неделе 20. Это рассказывает историю лучше, чем строчка в резюме.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель: репозиторий — дневник разработчика, а не архив готовых работ. Каждый коммит — запись «что сделано и зачем», а вместе они складываются в график активности на странице профиля GitHub. Пустые недели в этом графике так же красноречивы, как и активные.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Репозиторий создаёте под своим аккаунтом, пустым (без README, лицензии и .gitignore от GitHub — их вы добавите сами локально, чтобы первый коммит был осмысленным, а не автосгенерированным), затем клонируете себе на компьютер. Важно не путать: клонировать нужно свой пустой репозиторий, а не чужой существующий learning-log — иначе история коммитов будет принадлежать другому человеку, и смысл портфолио теряется.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно для всего маршрута: начиная с недели 1 каждый день заканчивается коммитом в эту же папку. Если репозиторий настроен неправильно сегодня — с чужой историей или без .gitignore — проблему придётся решать посреди недели 1, отвлекаясь от HTML.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что показывать портфолио стоит только после «идеального» результата, поэтому можно закоммитить всё одним большим коммитом в конце. На деле частые маленькие коммиты с понятными сообщениями (feat: add contact form, а не fix) сами по себе сигнал профессионализма — и заметны раньше, чем содержимое кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: репозиторий появляется до первой строки HTML — сегодняшняя практика это подтверждает: вы создаёте learning-log, .gitignore и README.md ещё до того, как напишете хоть один тег.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Аккаунт GitHub (если нет) + 2FA по возможности
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. New repository → имя learning-log → Public → без README / .gitignore / license
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Скопируйте URL и клонируйте:
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        git clone https://github.com/<ваш-логин>/learning-log.git\ncd learning-log\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создайте .gitignore:
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        echo -e ".DS_Store\\nThumbs.db\\n.env\\nnode_modules/\\n*.log\\n.venv/" > .gitignore\ngit add .gitignore\ngit commit -m "chore: init learning-log"\ngit push -u origin main\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создайте минимальный README.md: название, цель («прохожу web-roadmap»), ссылка на https://github.com/krwg/web-roadmap — закоммитьте
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создать пустой learning-log под своим аккаунтом
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Clone → .gitignore → первый push
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: репозиторий виден на github.com/ваш-логин/learning-log

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Permission denied / auth — используйте HTTPS + Personal Access Token или GitHub CLI (gh auth login). Ветка называется master вместо main — переименуйте: git branch -M main.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 0.3: Как учиться по маршруту

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~45м теория · ~40м практика · ~10м Git
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~25м практика
                                                                                                                                                                                                                        \nСвязь с проектом: выбрать полный или лайт-трек до недели 1

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Каждый учебный день недель 1–22 устроен одинаково:

                                                                                                                                                                                                                        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                                                                                                                                                                        БлокЗачем
                                                                                                                                                                                                                        ТеорияСвои слова + ссылки (MDN, книги). Не пропускать
                                                                                                                                                                                                                        Практика (полный)Все пункты ТЗ дня
                                                                                                                                                                                                                        Практика (лайт)MVP-подмножество, если мало времени
                                                                                                                                                                                                                        GitМинимум один осмысленный коммит
                                                                                                                                                                                                                        Если застрялПодсказка по теме дня, не копипаст
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Полный трек (~5–7 ч/день): максимум глубины, все пункты практики, углублённое ревью. Лайт (~3–4 ч): теория читается полностью, практика — только MVP-подмножество, коммит обязателен; проект недели сдаётся в урезанном DoD (Definition of Done) из каталога проектов — согласованный меньший набор требований, а не «сделаю потом».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно для следующих недель: если сегодня не разобраться, чем полный трек отличается от лайт, велик риск на неделе 5 обнаружить накопившееся отставание, которое сложно объяснить — просто не был понятен ожидаемый объём практики. Пример: студент на лайт-треке, который в день 3 недели 1 делает только MVP-пункты вместо всех пунктов «полного трека», не отстаёт — он следует своему треку, если проект недели в итоге собран по лайт-DoD.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Протокол «анти-вайбкодер» — отдельное важное правило: ИИ-ассистент в этом маршруте объясняет концепцию или ревьюит уже написанный вами код, но не пишет решение за вас. Частая ошибка новичков — попросить ИИ «сделай форму валидации» и скопировать ответ: код появится, а навык — нет, и это станет заметно на итоговом проекте. Сегодняшняя практика — прочитать introduction и каталог проектов, чтобы осознанно выбрать трек, а не выяснять правила на ходу в понедельник.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Введение\n- Каталог 22 проектов

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Прочитай introduction и обзор проектов
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. В learning-log создай journal.md — цель на 22 недели одним абзацем
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Открой сайт маршрута — закрепи вкладку
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Выбери трек (полный / лайт) и запиши выбор в journal
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Коммит: chore: add learning journal
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Прочитай introduction (хотя бы разделы «для кого» и «как устроен день»)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. journal.md с целью + закладка на сайт
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не знаете, полный или лайт — начните лайт на 3 дня. Если стабильно укладываетесь с запасом — переключитесь на полный со следующей недели.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Два трека нагрузки

                                                                                                                                                                                                                        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                                                                                                                                                                        ТрекЧасов/деньКогда выбирать
                                                                                                                                                                                                                        Полный~5–7Цель — junior full-stack, есть время
                                                                                                                                                                                                                        Лайт~3–4Работа/учёба параллельно; проект недели в MVP
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        В лайт-треке проект недели обязателен в урезанном виде — без него навык не склеится. Часы в днях недель 1–22 пересчитаны по объёму практики (не копипаст «1.5 + 2.5» на каждый день).

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nГотов ли я к неделе 1?\n\n- [ ] VS Code + браузер с DevTools работают\n- [ ] `learning-log` на **вашем** GitHub, есть `.gitignore` и хотя бы один коммит\n- [ ] Понимаю день: теория → практика (полный или лайт) → Git\n- [ ] Знаю, где открыть план недели на сайте\n- [ ] Выбран трек нагрузки\n\n
                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Неделя 1: HTML

                                                                                                                                                                                                                        ", "toc": [{"id": "week-00-зачем-отдельная-неделя-0", "label": "Зачем отдельная неделя 0"}, {"id": "week-00-day-0-1", "label": "День 0.1: Инструменты"}, {"id": "week-00-day-0-2", "label": "День 0.2: GitHub и свой learning-log"}, {"id": "week-00-day-0-3", "label": "День 0.3: Как учиться по маршруту"}, {"id": "week-00-два-трека-нагрузки", "label": "Два трека нагрузки"}, {"id": "week-00-review", "label": "Проверь себя"}], "text": "Неделя 0: Онбординг — до первого HTML Цель: подготовить инструменты, аккаунты и репозиторий learning-log до недели 1 . Время: 2–4 часа (один раз) Проект: инфраструктура обучения, не код недели Зачем отдельная неделя 0 Неделя 1 сразу про HTML и Git. Если VS Code, Git и GitHub не готовы — первый день уйдёт на установку, а не на index.html . Неделя 0 снимает трение: среда, аккаунт, репозиторий, понимание «как учиться». День 0.1: Инструменты Время (полный): ~40м теория · ~1.5ч практика · ~10м проверка Время (лайт): ~20м теория · ~45м практика Связь с проектом: стабильная среда для всех следующих недель Теория Веб-разработка начинается не с кода, а со среды : редактор, браузер с DevTools, терминал, Git. Эти инструменты останутся с вами на годы, поэтому час, потраченный сегодня на настройку, оку…"} \ No newline at end of file diff --git a/docs/weeks/01.json b/docs/weeks/01.json index 6df5c56..9ee63e5 100644 --- a/docs/weeks/01.json +++ b/docs/weeks/01.json @@ -1 +1 @@ -{"id": "week-01", "title": "HTML", "fullTitle": "Неделя 1: HTML — структура, семантика, формы, a11y", "html": "

                                                                                                                                                                                                                        Неделя 1: HTML — структура, семантика, формы, a11y

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: научиться создавать валидные, семантические HTML-страницы с формами и базовой доступностью — и с первого дня вести код в Git.\nПроект недели: Portfolio Landing — 3 страницы, форма, a11y ≥ 90.\nGit: репозиторий learning-log создаётся в день 1; первый коммит — index.html. К концу недели ≥ 7 коммитов, тег week-01-done.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература (обязательно + по желанию)

                                                                                                                                                                                                                        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                                                                                                                                                                        ПриоритетИсточникГлавы / разделы
                                                                                                                                                                                                                        ★★★Ионетт Дакетт «HTML и CSS»гл. 1–6
                                                                                                                                                                                                                        ★★★MDN Learn HTMLвесь трек
                                                                                                                                                                                                                        ★★web.dev Learn HTMLсемантика, формы
                                                                                                                                                                                                                        ★★Scott Chacon «Pro Git»гл. 1–2 — основы и коммиты
                                                                                                                                                                                                                        HTML5 Doctor (архив)семантические элементы
                                                                                                                                                                                                                        A11y Project Checklistдоступность
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 0 (до понедельника): Git и GitHub — подготовка

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~35м теория · ~1.5ч практика · ~10м Git · ~15м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~15м теория · ~40м практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если Git уже установлен и аккаунт GitHub есть — пройди чеклист и переходи к дню 1.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Система контроля версий (VCS) решает проблему, с которой каждый разработчик сталкивается рано: «что я менял, когда и зачем?». Без VCS папка проекта превращается в index_final_v3_REAL.html. Git хранит не отдельные патчи, а снимки всего проекта в момент коммита — как фотография комнаты, а не список «переставили стул на 3 см влево». Это позволяет мгновенно откатиться к любому состоянию, сравнить две версии и работать параллельно в ветках.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Рабочий процесс Git строится вокруг трёх зон. Working directory — файлы на диске, которые ты редактируешь прямо сейчас. Команда git add переносит выбранные изменения в staging (индекс) — зону подготовки: «вот это точно войдёт в следующий коммит». git commit фиксирует снимок staging в repository — локальной базе истории. Мысленная модель: черновик на столе → выбранные листы в папку «на подпись» → подписанный документ в архив.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        GitHub — это удалённое зеркало репозитория плюс социальная платформа. Публичный learning-log с осмысленной историей коммитов — живое портфолио: рекрутер видит не только код, но и то, как ты думаешь и работаешь.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: коммит — это именованный снимок проекта, а не просто «сохранить файл».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Pro Git: Введение — зачем VCS: история, откат, ветки

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Установи Git, проверь: git --version
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Настрой имя и email (они попадут в каждый коммит):
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай аккаунт на GitHub если нет
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Создай пустой публичный репозиторий learning-log (без README — добавишь локально)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Склонируй репозиторий learning-log (кнопка Code → HTTPS)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай .gitignore в корне:
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Первый коммит инфраструктуры:\n bash\n git config --global user.name \"Твоё Имя\"\n git config --global user.email \"you@example.com\"\n .DS_Store\n Thumbs.db\n .env\n *.log\n node_modules/\n bash\n cd learning-log\n git add .gitignore\n git commit -m \"chore: init learning-log with gitignore\"\n git push -u origin main
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] git status работает в папке learning-log\n- [ ] Репозиторий виден на GitHub\n- [ ] .gitignore закоммичен

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Установи Git, проверь: git --version
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Настрой имя и email (они попадут в каждый коммит):
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай аккаунт на GitHub если нет
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Создай пустой публичный репозиторий learning-log (без README — добавишь локально)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Структура документа, первый index.html, первый коммит страницы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1.5ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~35м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        HTML — это не язык оформления, а язык смысла. Когда браузер получает .html, он парсит разметку и строит DOM-дерево (Document Object Model) — живую структуру узлов в памяти. Представь генеалогическое древо: корень <html>, ветви <head> и <body>, листья — текст и элементы. CSS и JavaScript позже «цепляются» к этому дереву. Разметка описывает, что это за контент, а не как он выглядит.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Каждый документ начинается с <!DOCTYPE html>, который переключает браузер в standards mode — предсказуемое поведение вёрстки. Без DOCTYPE старые браузеры могут включить quirks mode и интерпретировать CSS иначе. В <head> живут метаданные: кодировка (charset), viewport для мобильных, заголовок вкладки. В <body> — всё, что видит пользователь.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Элементы делятся на блочные и строчные. Блочные (p, h1, ul) занимают всю ширину строки и начинаются с новой линии — как абзацы в книге. Строчные (span, a, img) текут внутри строки, как слова в предложении. Заголовки h1h6 задают иерархию разделов, а не размер шрифта: один логический h1 на страницу, затем h2 для подразделов. Прыжок с h1 сразу на h3 — как оглавление, где после главы 1 идёт 1.3 без главы 2.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Атрибуты дополняют теги: id — уникальный якорь (один на страницу), class — группа для стилей, href и src — адреса ссылок и ресурсов. У img атрибут alt обязателен, если картинка несёт смысл — иначе скринридер и поисковик не поймут, что на изображении.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: HTML описывает структуру и смысл; браузер из неё строит DOM-дерево.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Введение в HTML — разметка описывает смысл, браузер строит DOM-дерево

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. В learning-log создай папку week-01/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Файл week-01/index.html — корректный DOCTYPE, lang=\"ru\", meta charset=\"UTF-8\", viewport
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Секции: шапка с именем, nav из 3 якорных ссылок (#about, #skills, #contact)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Блоки «О себе», «Навыки» (ul), «Контакты» (p + ссылка mailto:)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Изображение-аватар с осмысленным alt; внешняя ссылка GitHub с target=\"_blank\" rel=\"noopener noreferrer\"
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Live Server → DevTools → Elements: найди DOM-узлы, соответствующие тегам
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. validator.w3.org — 0 errors
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        15. В week-01/README.md — 3 предложения: что за страница, как открыть локально
                                                                                                                                                                                                                        16. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Валидный HTML\n- [ ] Один h1, логичные h2\n- [ ] У img есть alt

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. В learning-log создай папку week-01/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Файл week-01/index.html — корректный DOCTYPE, lang=\"ru\", meta charset=\"UTF-8\", viewport
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Секции: шапка с именем, nav из 3 якорных ссылок (#about, #skills, #contact)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Блоки «О себе», «Навыки» (ul), «Контакты» (p + ссылка mailto:)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        cd learning-log\ngit add week-01/index.html week-01/README.md\ngit commit -m "week 01 day 1: first portfolio index.html with semantic sections"\ngit push\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это твой первый коммит кода — зафиксируй дату в journal.md (создай в корне, если ещё нет).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Пропуск DOCTYPE → непредсказуемая вёрстка в старых браузерах
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • h3 сразу после h1 без h2 — плохой document outline
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • div внутри p — невалидная вложенность
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Семантическая разметка

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Семантика в HTML — это выбор тега, который точно описывает роль элемента, а не просто «коробку для стилей». <div> ничего не говорит о содержимом; <nav> явно объявляет: здесь навигация. Браузер, скринридер и поисковик читают эту разметку и строят карту страницы. Пользователь с программой чтения с экрана может прыгнуть сразу к main, минуя шапку и меню — если ты их правильно разметил.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Landmark-элементы — ориентиры на странице: header (шапка), nav (меню), main (основной уникальный контент), footer (подвал). На странице должен быть ровно один main. nav — только для навигационных ссылок, не для любого списка ссылок в тексте. Страница с семантической разметкой читается логично даже без CSS — это хороший тест: отключи стили и проверь, понятна ли структура.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        section группирует тематически связанный контент с заголовком (блок «О себе», «Навыки»). article — самодостаточная единица: пост в блоге, карточка товара, новость — то, что можно вынести в RSS отдельно. aside — боковое дополнение к основному потоку: виджет «сейчас изучаю», реклама, сноски. Пара figure + figcaption связывает иллюстрацию с подписью; элемент time с атрибутом datetime даёт машиночитаемую дату для календарей и микроразметки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: правильный тег — это документация для людей и машин; div — последний выбор, не первый.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Семантика — тег несёт смысл для браузера, скринридера, SEO

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Рефакторинг index.html: убери «суп из div», введи header, nav, main, section, footer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. article — мини-пост «Почему я учу веб» с time
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. aside — список «Сейчас изучаю: HTML, Git»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. HeadingsMap или DevTools Accessibility — проверь outline
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Сравни diff в Git: git diff до коммита — видишь только структурные изменения?
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Один main на страницу\n- [ ] nav только для навигации\n- [ ] Структура читается без CSS

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Рефакторинг index.html: убери «суп из div», введи header, nav, main, section, footer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. article — мини-пост «Почему я учу веб» с time
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. aside — список «Сейчас изучаю: HTML, Git»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        git add week-01/index.html\ngit commit -m "week 01 day 2: refactor to semantic landmarks and article"\ngit push\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): Ссылки, изображения, медиа

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Многостраничный сайт связывается ссылками и путями к ресурсам. Относительные пути (./about.html, ../images/photo.jpg) привязаны к структуре папок проекта, а не к домену — перенеси папку на другой хостинг, и ссылки продолжат работать. Абсолютные URL с доменом (например example.com/page) нужны для внешних ресурсов. Якорные ссылки (#section-id) прыгают к элементу с соответствующим id на той же странице.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Изображения — отдельная дисциплина доступности и производительности. Атрибут alt описывает смысл картинки для тех, кто её не видит. Декоративное изображение получает alt=\"\" (пустой), чтобы скринридер его пропустил. Не дублируй текст из figcaption в alt — это раздражает при озвучивании дважды. Атрибут loading=\"lazy\" откладывает загрузку картинок ниже первого экрана, ускоряя начальную отрисовку. Пара srcset + sizes позволяет браузеру выбрать подходящий размер файла под экран — меньше трафика на мобильном.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Видео встраивается тегом <video> с controls для панели управления и poster — превью до воспроизведения. Текст внутри тега — fallback для старых браузеров: «Ваш браузер не поддерживает видео».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: alt — не украшение, а часть контента; пустой alt уместен только для декора.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Изображения в HTML\n- MDN: Responsive images

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. week-01/about.html, week-01/gallery.html — единый header/nav/footer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Относительные ссылки между страницами + якоря #section-id
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Галерея 4+ figure с WebP/JPG, lazy loading
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Одно video с poster (короткий клип о себе или placeholder)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Lighthouse Accessibility на index.html
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Обнови nav на всех страницах — активная страница через aria-current=\"page\" на текущей ссылке
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Нет битых ссылок\n- [ ] Внешние ссылки с rel=\"noopener noreferrer\"\n- [ ] aria-current на активном пункте nav

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. week-01/about.html, week-01/gallery.html — единый header/nav/footer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Относительные ссылки между страницами + якоря #section-id
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Галерея 4+ figure с WebP/JPG, lazy loading
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        git add week-01/\ngit commit -m "week 01 day 3: multi-page site with gallery and media"\ngit push\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): Формы — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Форма — мост между пользователем и сервером: собирает ввод и отправляет его. Даже на статическом сайте без бэкенда форма полезна для изучения: можно увидеть в DevTools → Network, какие данные ушли бы при submit. Атрибут action задаёт URL назначения; без него отправка идёт на текущий адрес страницы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Связка label[for=\"field-id\"] + input[id=\"field-id\"] — фундамент доступности форм. Клик по подписи фокусирует поле: удобно на мобильном и критично для пользователей скринридеров. Атрибут name на каждом поле — ключ, под которым значение попадёт в данные формы при отправке. Без name поле просто игнорируется.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Группировка через fieldset и legend объединяет связанные поля (например, radio-кнопки) с общим заголовком. У radio-кнопок в одной группе должен быть одинаковый name — иначе браузер не поймёт, что выбор взаимоисключающий. Внимание к типам кнопок: button без type внутри формы по умолчанию ведёт себя как submit и отправляет форму. Для обычной кнопки явно укажи type=\"button\".

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: каждое поле — с видимым label; name — имя данных при отправке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Your first form

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. На contact.html — форма: имя, email, тема (select), сообщение (textarea)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Radio «Способ связи», checkbox «Согласие» с required
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Каждое поле с видимым label
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. fieldset/legend для группы radio
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Submit — посмотри в DevTools → Network что ушло бы (или закрой форму onsubmit=\"return false\" для статики)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Все поля с labels\n- [ ] Radio с общим name\n- [ ] email type даёт нативную валидацию

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. На contact.html — форма: имя, email, тема (select), сообщение (textarea)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Radio «Способ связи», checkbox «Согласие» с required
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Каждое поле с видимым label
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        git add week-01/contact.html week-01/\ngit commit -m "week 01 day 4: contact form with labels and fieldsets"\ngit push\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Валидация форм

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        HTML5 принёс встроенную валидацию — браузер проверяет поля до отправки без единой строки JavaScript. Атрибуты required, minlength, pattern, type=\"email\" задают правила; при нарушении submit блокируется, и браузер показывает подсказку. За кулисами работает Constraint Validation API: у каждого поля есть объект validity со флагами (valueMissing, patternMismatch и др.) и свойство validationMessage с текстом ошибки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        В CSS псевдокласс :invalid позволяет подсветить проблемное поле — но осторожно: поле считается :invalid и до первого ввода, если оно required. Часто комбинируют с :user-invalid или вешают стили после попытки submit. Атрибут placeholder — серый текст-подсказка внутри поля, который исчезает при вводе. Он не заменяет label: пользователь, начав печатать, уже не видит, что от него хотели. datalist даёт выпадающие подсказки, но не ограничивает ввод — в отличие от select.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Клиентская валидация — удобство и ранняя обратная связь, но не защита: злоумышленник обойдёт её за секунду. На сервере проверять всё равно обязательно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: placeholder — подсказка, label — подпись; не путай их роли.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Form validation

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Форма регистрации на отдельной секции или register.html
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Пароль minlength=\"8\", логин pattern=\"[A-Za-z0-9_]{3,20}\"
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Два fieldset: «Личные данные», «Учётные данные»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. datalist для города (5+ городов)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Тест: пустая отправка, неверный email, короткий пароль — браузер блокирует
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Нативная валидация без JS\n- [ ] placeholder не единственная подпись\n- [ ] Понятные title у полей с pattern

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Форма регистрации на отдельной секции или register.html
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Пароль minlength=\"8\", логин pattern=\"[A-Za-z0-9_]{3,20}\"
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Два fieldset: «Личные данные», «Учётные данные»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        git add week-01/\ngit commit -m "week 01 day 5: registration form with HTML5 validation"\ngit push\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Две кнопки submit в одной форме
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • type=\"number\" для телефона — лучше type=\"tel\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Доступность (a11y)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Доступность (accessibility, a11y) — это не «галочка для инвалидов», а качество интерфейса для всех: плохой контраст мешает читать при ярком солнце, а чёткая навигация с клавиатуры спасает, когда мышь сломалась. Фреймворк POUR задаёт четыре принципа: контент должен быть воспринимаем (Perceivable), управляем (Operable), понятен (Understandable) и устойчив к разным технологиям (Robust).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Клавиатурная навигация — базовый тест. Порядок Tab следует порядку элементов в DOM, а не визуальному расположению на экране. Не ставь положительный tabindex без веской причины — это ломает естественный порядок. Skip link — первая фокусируемая ссылка «Перейти к содержимому», ведущая к #main-content; пользователь скринридера не слушает меню на каждой странице заново.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Контраст текста и фона по WCAG AA — минимум 4.5:1 для обычного текста и 3:1 для крупного. Проверяй через WebAIM Contrast Checker, а не «на глаз». ARIA-атрибуты (aria-label, role) дополняют HTML, когда нативного элемента нет — но первое правило ARIA: не используй ARIA, если подходит обычный тег (button вместо div с role=\"button\").

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: если страницу нельзя пройти Tab-ом — она недоступна, даже с идеальным дизайном.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- web.dev: Learn Accessibility — POUR: Perceivable, Operable, Understandable, Robust

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди все страницы только Tab/Enter/Space
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Skip-link в начале body на каждой странице
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. WebAIM Contrast Checker — исправь слабый контраст (временный inline style допустим)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Lighthouse a11y ≥ 90 на index.html
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Запиши в week-01/A11Y.md — 5 найденных проблем и как исправил
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Skip-link работает\n- [ ] Видимый :focus-visible на ссылках\n- [ ] Lighthouse ≥ 90

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди все страницы только Tab/Enter/Space
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Skip-link в начале body на каждой странице
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. WebAIM Contrast Checker — исправь слабый контраст (временный inline style допустим)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        git add week-01/\ngit commit -m "week 01 day 6: accessibility fixes and A11Y audit doc"\ngit push\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Таблицы, метаданные, проект недели

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        HTML-таблицы предназначены для табличных данных — расписания, сравнения, статистики. В 1990-х ими верстали макеты целых сайтов; сегодня для layout есть CSS Grid и Flexbox, а таблица для вёрстки — антипаттерн: скринридер зачитывает «строка 3, столбец 2» там, где пользователь ждёт заголовок статьи. Правильная таблица: caption (заголовок), thead с th scope=\"col\", tbody с td. Атрибут scope связывает заголовок с колонкой или строкой.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Метаданные в <head> влияют на то, как страницу видят извне. title — заголовок вкладки и сниппет в поиске. meta name=\"description\" — краткое описание для Google. Open Graph-теги (og:title, og:image) управляют превью при шаринге в Telegram или LinkedIn: без них мессенджер подставит случайный текст. Favicon — иконка вкладки: link rel=\"icon\" с PNG 32×32 или SVG для чёткости на Retina.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: таблица = данные с заголовками; для сетки страницы — CSS, не <table>.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Tablesth scope=\"col|row\", caption

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Таблица «План обучения» (неделя, тема, статус) на index.html
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Уникальные title и description на каждой странице
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. OG-теги на главной, favicon
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Финальный прогон W3C + Lighthouse на всех HTML
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Собери проект недели — чеклист ниже
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. notes.md в week-01/: 5 правил хорошего HTML своими словами
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Таблица с thead/tbody/th\n- [ ] Все страницы валидны\n- [ ] Проект недели выполнен

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Таблица «План обучения» (неделя, тема, статус) на index.html
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Уникальные title и description на каждой странице
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. OG-теги на главной, favicon
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        git add week-01/\ngit commit -m "week 01 day 7: tables, meta, favicon, week project complete"\ngit tag -a week-01-done -m "Portfolio Landing complete"\ngit push && git push --tags\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: Portfolio Landing

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Полное ТЗ: docs/projects.md#неделя-1--portfolio-landing

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Итоговые требования:\n- 3+ связанные страницы, единая навигация с aria-current\n- Форма контакта + форма регистрации с валидацией\n- Галерея, таблица навыков/плана, skip-links\n- Lighthouse a11y ≥ 90, W3C 0 errors\n- week-01/README.md со скриншотом и инструкцией запуска\n- ≥ 7 коммитов за неделю, тег week-01-done

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] Демо можно открыть через Live Server или GitHub Pages\n- [ ] Рекрутер понимает структуру без объяснений\n- [ ] git log --oneline week-01/ показывает осмысленную историю

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Объясняю разницу div vs section vs article?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Знаю, когда alt=\"\" уместен?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Связал label[for] с полем?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Настроил Git и сделал первый коммит index.html в день 1?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Могу проверить страницу валидатором и Lighthouse без подсказок?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Portfolio Landing** в `learning-log/week-01/`, осмысленная Git-история, тег `week-01-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nВалидный семантический HTML с формами и базовой доступностью\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-01-day-0", "label": "День 0 (до понедельника): Git и GitHub — подготовка"}, {"id": "week-01-day-1", "label": "День 1 (Mon): Структура документа, первый index.html, первый"}, {"id": "week-01-day-2", "label": "День 2 (Tue): Семантическая разметка"}, {"id": "week-01-day-3", "label": "День 3 (Wed): Ссылки, изображения, медиа"}, {"id": "week-01-day-4", "label": "День 4 (Thu): Формы — основы"}, {"id": "week-01-day-5", "label": "День 5 (Fri): Валидация форм"}, {"id": "week-01-day-6", "label": "День 6 (Sat): Доступность (a11y)"}, {"id": "week-01-day-7", "label": "День 7 (Sun): Таблицы, метаданные, проект недели"}, {"id": "week-01-проект-недели-portfolio-landing", "label": "Проект недели: Portfolio Landing"}, {"id": "week-01-review", "label": "Ревью-чеклист"}], "text": "Неделя 1: HTML — структура, семантика, формы, a11y Цель недели: научиться создавать валидные, семантические HTML-страницы с формами и базовой доступностью — и с первого дня вести код в Git. Проект недели: Portfolio Landing — 3 страницы, форма, a11y ≥ 90. Git: репозиторий learning-log создаётся в день 1 ; первый коммит — index.html . К концу недели ≥ 7 коммитов, тег week-01-done . Литература (обязательно + по желанию) Приоритет Источник Главы / разделы ★★★ Ионетт Дакетт «HTML и CSS» гл. 1–6 ★★★ MDN Learn HTML весь трек ★★ web.dev Learn HTML семантика, формы ★★ Scott Chacon «Pro Git» гл. 1–2 — основы и коммиты ★ HTML5 Doctor (архив) семантические элементы ★ A11y Project Checklist доступность День 0 (до понедельника): Git и GitHub — подготовка Время (полный): ~35м теория · ~1.5ч практика · ~1…"} \ No newline at end of file +{"id": "week-01", "title": "HTML", "fullTitle": "Неделя 1: HTML — структура, семантика, формы, a11y", "html": "

                                                                                                                                                                                                                        Неделя 1: HTML — структура, семантика, формы, a11y

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: научиться создавать валидные, семантические HTML-страницы с формами и базовой доступностью — и с первого дня вести код в Git.\nПроект недели: Portfolio Landing — 3 страницы, форма, a11y ≥ 90.\nGit: репозиторий learning-log создаётся в день 1; первый коммит — index.html. К концу недели ≥ 7 коммитов, тег week-01-done.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература (обязательно + по желанию)

                                                                                                                                                                                                                        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                                                                                                                                                                        ПриоритетИсточникГлавы / разделы
                                                                                                                                                                                                                        ★★★Ионетт Дакетт «HTML и CSS»гл. 1–6
                                                                                                                                                                                                                        ★★★MDN Learn HTMLвесь трек
                                                                                                                                                                                                                        ★★web.dev Learn HTMLсемантика, формы
                                                                                                                                                                                                                        ★★Scott Chacon «Pro Git»гл. 1–2 — основы и коммиты
                                                                                                                                                                                                                        HTML5 Doctor (архив)семантические элементы
                                                                                                                                                                                                                        A11y Project Checklistдоступность
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 0 (до понедельника): Git и GitHub — подготовка

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~1.5ч практика · ~10м Git · ~15м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~40м практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если Git уже установлен и аккаунт GitHub есть — пройди чеклист и переходи к дню 1.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Система контроля версий (VCS) решает проблему, с которой каждый разработчик сталкивается рано: «что я менял, когда и зачем?». Без VCS папка проекта превращается в index_final_v3_REAL.html. Git хранит не отдельные патчи, а снимки всего проекта в момент коммита — как фотография комнаты, а не список «переставили стул на 3 см влево». Это позволяет мгновенно откатиться к любому состоянию, сравнить две версии и работать параллельно в ветках.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Рабочий процесс Git строится вокруг трёх зон. Working directory — файлы на диске, которые ты редактируешь прямо сейчас. Команда git add переносит выбранные изменения в staging (индекс) — зону подготовки: «вот это точно войдёт в следующий коммит». git commit фиксирует снимок staging в repository — локальной базе истории. Мысленная модель: черновик на столе → выбранные листы в папку «на подпись» → подписанный документ в архив.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        GitHub — это удалённое зеркало репозитория плюс социальная платформа. Публичный learning-log с осмысленной историей коммитов — живое портфолио: рекрутер видит не только код, но и то, как ты думаешь и работаешь.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это критично для всех следующих 22 недель: каждый день маршрута заканчивается коммитом, и от того, насколько уверенно ты сегодня освоишь addcommitpush, зависит, будет ли Git помогать или пугать всю дорогу. На неделе 6 появятся ветки для фич, дальше — пул-реквесты и код-ревью; без твёрдой базы трёх зон эти темы превращаются в магию вместо инструмента.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример рабочего цикла: правишь index.html, git status показывает файл как изменённый (working directory), git add index.html переносит его в staging, git commit -m \"...\" создаёт снимок в истории, git push отправляет его на GitHub — до этого момента изменения видны только тебе локально.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение новичков — считать, что git add уже «сохраняет» изменения, и после него можно закрыть терминал. На деле без git commit изменения остаются в staging и никуда не «доезжают»; а без git push коммит остаётся только на твоём компьютере и не появится на GitHub, даже если локально git log показывает его.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: коммит — это именованный снимок проекта, а не просто «сохранить файл»; сегодняшняя практика — прогнать этот цикл от установки Git до первого git push вручную, чтобы завтра, в день 1, писать index.html и коммитить его уже не задумываясь о механике.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Pro Git: Введение — зачем VCS: история, откат, ветки

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Установи Git, проверь: git --version
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Настрой имя и email (они попадут в каждый коммит):
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай аккаунт на GitHub если нет
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Создай пустой публичный репозиторий learning-log (без README — добавишь локально)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Склонируй репозиторий learning-log (кнопка Code → HTTPS)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай .gitignore в корне:
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Первый коммит инфраструктуры:\n bash\n git config --global user.name \"Твоё Имя\"\n git config --global user.email \"you@example.com\"\n .DS_Store\n Thumbs.db\n .env\n *.log\n node_modules/\n bash\n cd learning-log\n git add .gitignore\n git commit -m \"chore: init learning-log with gitignore\"\n git push -u origin main
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] git status работает в папке learning-log\n- [ ] Репозиторий виден на GitHub\n- [ ] .gitignore закоммичен

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Установи Git, проверь: git --version
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Настрой имя и email (они попадут в каждый коммит):
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай аккаунт на GitHub если нет
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Создай пустой публичный репозиторий learning-log (без README — добавишь локально)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Структура документа, первый index.html, первый коммит страницы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        HTML — это не язык оформления, а язык смысла. Когда браузер получает .html, он парсит разметку и строит DOM-дерево (Document Object Model) — живую структуру узлов в памяти. Представь генеалогическое древо: корень <html>, ветви <head> и <body>, листья — текст и элементы. CSS и JavaScript позже «цепляются» к этому дереву. Разметка описывает, что это за контент, а не как он выглядит.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Каждый документ начинается с <!DOCTYPE html>, который переключает браузер в standards mode — предсказуемое поведение вёрстки. Без DOCTYPE старые браузеры могут включить quirks mode и интерпретировать CSS иначе. В <head> живут метаданные: кодировка (charset), viewport для мобильных, заголовок вкладки. В <body> — всё, что видит пользователь.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Элементы делятся на блочные и строчные. Блочные (p, h1, ul) занимают всю ширину строки и начинаются с новой линии — как абзацы в книге. Строчные (span, a, img) текут внутри строки, как слова в предложении. Заголовки h1h6 задают иерархию разделов, а не размер шрифта: один логический h1 на страницу, затем h2 для подразделов. Прыжок с h1 сразу на h3 — как оглавление, где после главы 1 идёт 1.3 без главы 2.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Атрибуты дополняют теги: id — уникальный якорь (один на страницу), class — группа для стилей, href и src — адреса ссылок и ресурсов. У img атрибут alt обязателен, если картинка несёт смысл — иначе скринридер и поисковик не поймут, что на изображении.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель, которая пригодится на всех следующих неделях: HTML — это скелет, CSS (неделя 2) — одежда и внешний вид, JavaScript (неделя 4+) — мышцы и поведение. Скелет должен быть правильным сам по себе, ещё до того, как на него что-то надето: скринридер и поисковик читают именно разметку, а не то, как страница выглядит визуально после стилизации.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: если сверстать блок «Обо мне» через <div><div>Обо мне</div><div>Текст...</div></div>, страница может выглядеть нормально после CSS, но программа чтения с экрана объявит просто «группа, группа» — пользователь не поймёт, что перед ним заголовок раздела. Замена на <h2>Обо мне</h2><p>Текст...</p> решает проблему без единой строчки CSS.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение новичков — писать <div> и <span> для всего подряд «а потом стилями сделаю красиво», откладывая выбор семантики на потом. На деле семантика закладывается сразу: разметка описывает смысл контента независимо от того, как он будет оформлен, и переписывать структуру после того, как всё завязано на классы, дороже, чем сделать правильно с первого раза. Сегодняшняя практика — первый index.html — это и есть тренировка такого выбора: заголовки по иерархии, nav для навигации, осмысленный alt у изображения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: HTML описывает структуру и смысл; браузер из неё строит DOM-дерево, а CSS и JS лишь надстраиваются сверху.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Введение в HTML — разметка описывает смысл, браузер строит DOM-дерево

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. В learning-log создай папку week-01/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Файл week-01/index.html — корректный DOCTYPE, lang=\"ru\", meta charset=\"UTF-8\", viewport
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Секции: шапка с именем, nav из 3 якорных ссылок (#about, #skills, #contact)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Блоки «О себе», «Навыки» (ul), «Контакты» (p + ссылка mailto:)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Изображение-аватар с осмысленным alt; внешняя ссылка GitHub с target=\"_blank\" rel=\"noopener noreferrer\"
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Live Server → DevTools → Elements: найди DOM-узлы, соответствующие тегам
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. validator.w3.org — 0 errors
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        15. В week-01/README.md — 3 предложения: что за страница, как открыть локально
                                                                                                                                                                                                                        16. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Валидный HTML\n- [ ] Один h1, логичные h2\n- [ ] У img есть alt

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. В learning-log создай папку week-01/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Файл week-01/index.html — корректный DOCTYPE, lang=\"ru\", meta charset=\"UTF-8\", viewport
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Секции: шапка с именем, nav из 3 якорных ссылок (#about, #skills, #contact)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Блоки «О себе», «Навыки» (ul), «Контакты» (p + ссылка mailto:)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        cd learning-log\ngit add week-01/index.html week-01/README.md\ngit commit -m "week 01 day 1: first portfolio index.html with semantic sections"\ngit push\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это твой первый коммит кода — зафиксируй дату в journal.md (создай в корне, если ещё нет).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Пропуск DOCTYPE → непредсказуемая вёрстка в старых браузерах
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • h3 сразу после h1 без h2 — плохой document outline
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • div внутри p — невалидная вложенность
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Семантическая разметка

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Семантика в HTML — это выбор тега, который точно описывает роль элемента, а не просто «коробку для стилей». <div> ничего не говорит о содержимом; <nav> явно объявляет: здесь навигация. Браузер, скринридер и поисковик читают эту разметку и строят карту страницы. Пользователь с программой чтения с экрана может прыгнуть сразу к main, минуя шапку и меню — если ты их правильно разметил.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Landmark-элементы — ориентиры на странице: header (шапка), nav (меню), main (основной уникальный контент), footer (подвал). На странице должен быть ровно один main. nav — только для навигационных ссылок, не для любого списка ссылок в тексте. Страница с семантической разметкой читается логично даже без CSS — это хороший тест: отключи стили и проверь, понятна ли структура.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        section группирует тематически связанный контент с заголовком (блок «О себе», «Навыки»). article — самодостаточная единица: пост в блоге, карточка товара, новость — то, что можно вынести в RSS отдельно. aside — боковое дополнение к основному потоку: виджет «сейчас изучаю», реклама, сноски. Пара figure + figcaption связывает иллюстрацию с подписью; элемент time с атрибутом datetime даёт машиночитаемую дату для календарей и микроразметки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель: представь страницу как здание с указателями. header — вывеска у входа, nav — карта этажей у лифта, main — сам этаж с содержимым, aside — информационный стенд в коридоре, footer — табличка на выходе. Указатели помогают ориентироваться даже тому, кто не видит всё здание целиком — например, идёт по нему на ощупь, как скринридер идёт по DOM.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: на неделе 6 ты добавишь JavaScript, который будет искать элементы по структуре страницы (document.querySelector('main'), обработчики на nav a), а на неделях с React — компоненты будут возвращать именно такую семантическую разметку. Если сегодня привыкнуть мыслить landmark-ами, а не «div с классом wrapper», работа с фреймворками пойдёт быстрее.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: <div class=\"post\"><div class=\"post-title\">Заголовок</div><div class=\"post-date\">1 августа</div></div> технически работает, но <article><h2>Заголовок</h2><time datetime=\"2026-08-01\">1 августа</time></article> даёт браузеру и поисковику готовую структуру поста без единой строчки JS.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — использовать section для любого визуального блока с отступом. section уместен только когда у контента есть собственный заголовок и он тематически целостен; блок для чисто визуального разделения (например, обёртка для центрирования) так и остаётся div. Сегодня в практике ты рефакторишь вчерашний index.html именно с этим фильтром: «у этого блока есть заголовок и смысл, или это просто обёртка для стилей?»

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: правильный тег — это документация для людей и машин; div — последний выбор, не первый.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Семантика — тег несёт смысл для браузера, скринридера, SEO

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Рефакторинг index.html: убери «суп из div», введи header, nav, main, section, footer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. article — мини-пост «Почему я учу веб» с time
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. aside — список «Сейчас изучаю: HTML, Git»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. HeadingsMap или DevTools Accessibility — проверь outline
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Сравни diff в Git: git diff до коммита — видишь только структурные изменения?
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Один main на страницу\n- [ ] nav только для навигации\n- [ ] Структура читается без CSS

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Рефакторинг index.html: убери «суп из div», введи header, nav, main, section, footer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. article — мини-пост «Почему я учу веб» с time
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. aside — список «Сейчас изучаю: HTML, Git»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        git add week-01/index.html\ngit commit -m "week 01 day 2: refactor to semantic landmarks and article"\ngit push\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): Ссылки, изображения, медиа

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Многостраничный сайт связывается ссылками и путями к ресурсам. Относительные пути (./about.html, ../images/photo.jpg) привязаны к структуре папок проекта, а не к домену — перенеси папку на другой хостинг, и ссылки продолжат работать. Абсолютные URL с доменом (например example.com/page) нужны для внешних ресурсов. Якорные ссылки (#section-id) прыгают к элементу с соответствующим id на той же странице.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Изображения — отдельная дисциплина доступности и производительности. Атрибут alt описывает смысл картинки для тех, кто её не видит. Декоративное изображение получает alt=\"\" (пустой), чтобы скринридер его пропустил. Не дублируй текст из figcaption в alt — это раздражает при озвучивании дважды. Атрибут loading=\"lazy\" откладывает загрузку картинок ниже первого экрана, ускоряя начальную отрисовку. Пара srcset + sizes позволяет браузеру выбрать подходящий размер файла под экран — меньше трафика на мобильном.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Видео встраивается тегом <video> с controls для панели управления и poster — превью до воспроизведения. Текст внутри тега — fallback для старых браузеров: «Ваш браузер не поддерживает видео».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель для путей: относительный путь — это инструкция «иди отсюда», а не «иди по этому адресу в интернете». Если файл about.html лежит рядом с index.html, ссылка ./about.html сработает где угодно — на твоём компьютере, на GitHub Pages, на любом хостинге — потому что она описывает взаимное расположение файлов, а не конкретный домен.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: на неделе 9+ с системами сборки (Vite, Webpack) пути к изображениям и скриптам будут переписываться автоматически, но принцип «относительно текущего файла» останется тем же — непонимание разницы ./, ../ и / в начале пути — частый источник «битых картинок после деплоя» даже у опытных разработчиков.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: галерея с 10 фотографиями по 3 МБ каждая без loading=\"lazy\" загрузит все 30 МБ сразу при открытии страницы, даже если пользователь видит только первые три — это заметно тормозит мобильный интернет. С loading=\"lazy\" браузер подгружает картинку только когда она приближается к области видимости при скролле.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать, что alt=\"\" означает «забыл добавить описание». На самом деле пустой alt — осознанное решение для декоративной картинки (орнамент, разделитель), и скринридер тогда молча её пропускает; отсутствие атрибута alt вообще — это ошибка, при которой скринридер зачитывает весь путь к файлу. В сегодняшней практике, добавляя аватар и галерею, различай эти два случая осознанно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: alt — не украшение, а часть контента; пустой alt уместен только для декора, а не как способ сэкономить время на описании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Изображения в HTML\n- MDN: Responsive images

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. week-01/about.html, week-01/gallery.html — единый header/nav/footer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Относительные ссылки между страницами + якоря #section-id
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Галерея 4+ figure с WebP/JPG, lazy loading
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Одно video с poster (короткий клип о себе или placeholder)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Lighthouse Accessibility на index.html
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Обнови nav на всех страницах — активная страница через aria-current=\"page\" на текущей ссылке
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Нет битых ссылок\n- [ ] Внешние ссылки с rel=\"noopener noreferrer\"\n- [ ] aria-current на активном пункте nav

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. week-01/about.html, week-01/gallery.html — единый header/nav/footer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Относительные ссылки между страницами + якоря #section-id
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Галерея 4+ figure с WebP/JPG, lazy loading
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        git add week-01/\ngit commit -m "week 01 day 3: multi-page site with gallery and media"\ngit push\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): Формы — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Форма — мост между пользователем и сервером: собирает ввод и отправляет его. Даже на статическом сайте без бэкенда форма полезна для изучения: можно увидеть в DevTools → Network, какие данные ушли бы при submit. Атрибут action задаёт URL назначения; без него отправка идёт на текущий адрес страницы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Связка label[for=\"field-id\"] + input[id=\"field-id\"] — фундамент доступности форм. Клик по подписи фокусирует поле: удобно на мобильном и критично для пользователей скринридеров. Атрибут name на каждом поле — ключ, под которым значение попадёт в данные формы при отправке. Без name поле просто игнорируется.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Группировка через fieldset и legend объединяет связанные поля (например, radio-кнопки) с общим заголовком. У radio-кнопок в одной группе должен быть одинаковый name — иначе браузер не поймёт, что выбор взаимоисключающий. Внимание к типам кнопок: button без type внутри формы по умолчанию ведёт себя как submit и отправляет форму. Для обычной кнопки явно укажи type=\"button\".

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель: форма — это посылка на почте. name каждого поля — надпись на коробке («имя», «email»), value — содержимое коробки, а action — адрес получателя. Если на коробке нет надписи (name отсутствует), почта её просто не примет — данные потеряются ещё до отправки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: на неделях 11+ с бэкендом ты будешь получать те самые пары name: value на сервере (req.body.email) — если сегодня не разобраться, откуда берутся эти имена полей, серверная обработка форм превратится в чёрный ящик. А на неделе 6 с JavaScript ты научишься перехватывать submit и отправлять данные без перезагрузки страницы (fetch), но структура данных останется той же, что задаёт HTML сегодня.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: два radio-инпута с name=\"contact-method\" и разными value («email», «phone») образуют одну группу, где выбор одного автоматически снимает выбор другого. Если по ошибке дать им разные name, оба чекбокса смогут быть выбраны одновременно — форма перестанет быть «выбери один вариант».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение новичков — считать, что placeholder заменяет label, ведь текст и так виден в поле. На деле placeholder исчезает при вводе и не связан с полем программно — скринридер его может не объявить как подпись. В сегодняшней практике каждое поле должно получить настоящий видимый label, даже если рядом есть placeholder для дополнительной подсказки формата.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: каждое поле — с видимым label; name — имя данных при отправке, а не декоративный атрибут.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Your first form

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. На contact.html — форма: имя, email, тема (select), сообщение (textarea)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Radio «Способ связи», checkbox «Согласие» с required
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Каждое поле с видимым label
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. fieldset/legend для группы radio
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Submit — посмотри в DevTools → Network что ушло бы (или закрой форму onsubmit=\"return false\" для статики)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Все поля с labels\n- [ ] Radio с общим name\n- [ ] email type даёт нативную валидацию

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. На contact.html — форма: имя, email, тема (select), сообщение (textarea)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Radio «Способ связи», checkbox «Согласие» с required
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Каждое поле с видимым label
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        git add week-01/contact.html week-01/\ngit commit -m "week 01 day 4: contact form with labels and fieldsets"\ngit push\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Валидация форм

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        HTML5 принёс встроенную валидацию — браузер проверяет поля до отправки без единой строки JavaScript. Атрибуты required, minlength, pattern, type=\"email\" задают правила; при нарушении submit блокируется, и браузер показывает подсказку. За кулисами работает Constraint Validation API: у каждого поля есть объект validity со флагами (valueMissing, patternMismatch и др.) и свойство validationMessage с текстом ошибки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        В CSS псевдокласс :invalid позволяет подсветить проблемное поле — но осторожно: поле считается :invalid и до первого ввода, если оно required. Часто комбинируют с :user-invalid или вешают стили после попытки submit. Атрибут placeholder — серый текст-подсказка внутри поля, который исчезает при вводе. Он не заменяет label: пользователь, начав печатать, уже не видит, что от него хотели. datalist даёт выпадающие подсказки, но не ограничивает ввод — в отличие от select.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Клиентская валидация — удобство и ранняя обратная связь, но не защита: злоумышленник обойдёт её за секунду, отправив запрос напрямую в обход браузера. На сервере проверять всё равно обязательно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель: pattern и required — это турникет на входе в метро, а серверная валидация — охрана внутри здания. Турникет удобен и отсекает большинство случайных нарушителей, но полагаться только на него нельзя — до сервера с реальной проверкой долетит что угодно, если турникет обойти напрямую через инструменты разработчика или curl.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: на неделях 11–14 с бэкендом ты будешь писать серверную валидацию тех же самых полей — зная уже сегодня, какие правила выражает pattern и required на клиенте, легче понять, зачем дублировать похожую логику на сервере (спойлер: потому что клиенту нельзя доверять).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: pattern=\"[A-Za-z0-9_]{3,20}\" для логина не пропустит пробелы и спецсимволы, а браузер покажет стандартную подсказку — но без title=\"Только буквы, цифры и подчёркивание, 3-20 символов\" пользователь не поймёт, что именно не так, увидит просто «Please match the requested format».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что type=\"email\" полностью гарантирует валидный email. На деле встроенная проверка лишь требует наличие @ и домена по упрощённому шаблону — a@a пройдёт, а несуществующий домен ivan@nosuchdomain123.zzz тоже пройдёт, ведь синтаксически он корректен. Реальную проверку существования email делает только сервер, отправляя письмо-подтверждение.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: placeholder — подсказка, label — подпись; не путай их роли, и не путай клиентскую валидацию с настоящей защитой данных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Form validation

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Форма регистрации на отдельной секции или register.html
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Пароль minlength=\"8\", логин pattern=\"[A-Za-z0-9_]{3,20}\"
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Два fieldset: «Личные данные», «Учётные данные»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. datalist для города (5+ городов)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Тест: пустая отправка, неверный email, короткий пароль — браузер блокирует
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Нативная валидация без JS\n- [ ] placeholder не единственная подпись\n- [ ] Понятные title у полей с pattern

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Форма регистрации на отдельной секции или register.html
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Пароль minlength=\"8\", логин pattern=\"[A-Za-z0-9_]{3,20}\"
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Два fieldset: «Личные данные», «Учётные данные»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        git add week-01/\ngit commit -m "week 01 day 5: registration form with HTML5 validation"\ngit push\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Две кнопки submit в одной форме
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • type=\"number\" для телефона — лучше type=\"tel\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Доступность (a11y)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Доступность (accessibility, a11y) — это не «галочка для инвалидов», а качество интерфейса для всех: плохой контраст мешает читать при ярком солнце, а чёткая навигация с клавиатуры спасает, когда мышь сломалась. Фреймворк POUR задаёт четыре принципа: контент должен быть воспринимаем (Perceivable), управляем (Operable), понятен (Understandable) и устойчив к разным технологиям (Robust).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Клавиатурная навигация — базовый тест. Порядок Tab следует порядку элементов в DOM, а не визуальному расположению на экране. Не ставь положительный tabindex без веской причины — это ломает естественный порядок. Skip link — первая фокусируемая ссылка «Перейти к содержимому», ведущая к #main-content; пользователь скринридера не слушает меню на каждой странице заново.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Контраст текста и фона по WCAG AA — минимум 4.5:1 для обычного текста и 3:1 для крупного. Проверяй через WebAIM Contrast Checker, а не «на глаз». ARIA-атрибуты (aria-label, role) дополняют HTML, когда нативного элемента нет — но первое правило ARIA: не используй ARIA, если подходит обычный тег (button вместо div с role=\"button\").

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель: представь, что весь сайт нужно пройти с закрытыми глазами и только с клавиатурой — это буквально то, как его использует часть аудитории. Всё, что требует «просто увидеть цвет» или «просто кликнуть мышкой точно в маленькую область», для такого пользователя не существует. a11y — это проектирование сразу для этого сценария, а не патч поверх готового интерфейса.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: вся вёрстка недель 2-3 (Flexbox, Grid, анимации) и весь JavaScript с недели 4 будут либо сохранять, либо ломать доступность, заложенную сегодня. Модальные окна, кастомные дропдауны, drag-and-drop на JS — везде придётся explicitly управлять фокусом и ARIA-атрибутами, и без сегодняшней базы POUR эти темы будут восприниматься как произвольный список правил, а не система.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: кастомная кнопка <div onclick=\"...\">Отправить</div> выглядит как кнопка, но не получает фокус по Tab, не реагирует на Enter/Space и не объявляется скринридером как кнопка — три уровня доступности сломаны одним неверным выбором тега. <button>Отправить</button> даёт всё это бесплатно, без единой строчки ARIA.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что ARIA-атрибуты «чинят» доступность любого элемента. role=\"button\" на div сообщает скринридеру, что это кнопка, но не добавляет фокусируемость и обработку клавиатуры — это придётся программировать вручную на JS. Отсюда и «первое правило ARIA»: нативный button уже умеет всё это сам.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: если страницу нельзя пройти Tab-ом — она недоступна, даже с идеальным дизайном; сегодняшний аудит A11Y.md — тренировка смотреть на свою вёрстку глазами другого пользователя.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- web.dev: Learn Accessibility — POUR: Perceivable, Operable, Understandable, Robust

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди все страницы только Tab/Enter/Space
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Skip-link в начале body на каждой странице
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. WebAIM Contrast Checker — исправь слабый контраст (временный inline style допустим)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Lighthouse a11y ≥ 90 на index.html
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Запиши в week-01/A11Y.md — 5 найденных проблем и как исправил
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Skip-link работает\n- [ ] Видимый :focus-visible на ссылках\n- [ ] Lighthouse ≥ 90

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди все страницы только Tab/Enter/Space
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Skip-link в начале body на каждой странице
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. WebAIM Contrast Checker — исправь слабый контраст (временный inline style допустим)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        git add week-01/\ngit commit -m "week 01 day 6: accessibility fixes and A11Y audit doc"\ngit push\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Таблицы, метаданные, проект недели

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        HTML-таблицы предназначены для табличных данных — расписания, сравнения, статистики. В 1990-х ими верстали макеты целых сайтов; сегодня для layout есть CSS Grid и Flexbox, а таблица для вёрстки — антипаттерн: скринридер зачитывает «строка 3, столбец 2» там, где пользователь ждёт заголовок статьи. Правильная таблица: caption (заголовок), thead с th scope=\"col\", tbody с td. Атрибут scope связывает заголовок с колонкой или строкой.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Метаданные в <head> влияют на то, как страницу видят извне. title — заголовок вкладки и сниппет в поиске. meta name=\"description\" — краткое описание для Google. Open Graph-теги (og:title, og:image) управляют превью при шаринге в Telegram или LinkedIn: без них мессенджер подставит случайный текст. Favicon — иконка вкладки: link rel=\"icon\" с PNG 32×32 или SVG для чёткости на Retina.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель: <table> — это таблица в Excel, где каждая ячейка осмысленно связана со своей строкой и колонкой; если убрать эту связь (например, свёрстать «таблицу» через div), теряется не визуальный вид, а именно смысл — какое число к какой строке относится. Метаданные же — это витрина страницы: их не видно на самой странице, но именно по ним решают, кликать ли на ссылку в поиске или в мессенджере.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: сегодня — последний день недели, и именно метаданные (title, description, OG-теги) часто оказываются той мелочью, которая отличает «просто сайт» от «сайта, готового к реальному использованию» — в портфолио на неделе 22 это будет заметно сразу при шаринге ссылки в чат. Таблицы вернутся при работе с данными на бэкенде (недели 11+), где то же правило «заголовок связан со значением через scope или id/headers» останется актуальным.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: репост ссылки на твой learning-log в Telegram без OG-тегов покажет случайный кусок текста и, возможно, неподходящую картинку; с og:title, og:description и og:image — аккуратную карточку с твоим именем проекта и превью.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — тянуть в <table> данные, у которых на самом деле нет двух осей сравнения, просто потому что «так аккуратнее выглядит визуально». Список из одной колонки — это ul, а не таблица из одного столбца; таблица оправдана, когда данные реально пересекаются по строке и столбцу (неделя × статус, товар × цена).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: таблица = данные с заголовками; для сетки страницы — CSS, не <table>, а для видимости в поиске и мессенджерах — метаданные, а не только красивый дизайн.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Tablesth scope=\"col|row\", caption

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Таблица «План обучения» (неделя, тема, статус) на index.html
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Уникальные title и description на каждой странице
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. OG-теги на главной, favicon
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Финальный прогон W3C + Lighthouse на всех HTML
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Собери проект недели — чеклист ниже
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. notes.md в week-01/: 5 правил хорошего HTML своими словами
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Таблица с thead/tbody/th\n- [ ] Все страницы валидны\n- [ ] Проект недели выполнен

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Таблица «План обучения» (неделя, тема, статус) на index.html
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Уникальные title и description на каждой странице
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. OG-теги на главной, favicon
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        git add week-01/\ngit commit -m "week 01 day 7: tables, meta, favicon, week project complete"\ngit tag -a week-01-done -m "Portfolio Landing complete"\ngit push && git push --tags\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: Portfolio Landing

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Полное ТЗ: docs/projects.md#неделя-1--portfolio-landing

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Итоговые требования:\n- 3+ связанные страницы, единая навигация с aria-current\n- Форма контакта + форма регистрации с валидацией\n- Галерея, таблица навыков/плана, skip-links\n- Lighthouse a11y ≥ 90, W3C 0 errors\n- week-01/README.md со скриншотом и инструкцией запуска\n- ≥ 7 коммитов за неделю, тег week-01-done

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] Демо можно открыть через Live Server или GitHub Pages\n- [ ] Рекрутер понимает структуру без объяснений\n- [ ] git log --oneline week-01/ показывает осмысленную историю

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Объясняю разницу div vs section vs article?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Знаю, когда alt=\"\" уместен?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Связал label[for] с полем?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Настроил Git и сделал первый коммит index.html в день 1?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Могу проверить страницу валидатором и Lighthouse без подсказок?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Portfolio Landing** в `learning-log/week-01/`, осмысленная Git-история, тег `week-01-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nВалидный семантический HTML с формами и базовой доступностью\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-01-day-0", "label": "День 0 (до понедельника): Git и GitHub — подготовка"}, {"id": "week-01-day-1", "label": "День 1 (Mon): Структура документа, первый index.html, первый"}, {"id": "week-01-day-2", "label": "День 2 (Tue): Семантическая разметка"}, {"id": "week-01-day-3", "label": "День 3 (Wed): Ссылки, изображения, медиа"}, {"id": "week-01-day-4", "label": "День 4 (Thu): Формы — основы"}, {"id": "week-01-day-5", "label": "День 5 (Fri): Валидация форм"}, {"id": "week-01-day-6", "label": "День 6 (Sat): Доступность (a11y)"}, {"id": "week-01-day-7", "label": "День 7 (Sun): Таблицы, метаданные, проект недели"}, {"id": "week-01-проект-недели-portfolio-landing", "label": "Проект недели: Portfolio Landing"}, {"id": "week-01-review", "label": "Ревью-чеклист"}], "text": "Неделя 1: HTML — структура, семантика, формы, a11y Цель недели: научиться создавать валидные, семантические HTML-страницы с формами и базовой доступностью — и с первого дня вести код в Git. Проект недели: Portfolio Landing — 3 страницы, форма, a11y ≥ 90. Git: репозиторий learning-log создаётся в день 1 ; первый коммит — index.html . К концу недели ≥ 7 коммитов, тег week-01-done . Литература (обязательно + по желанию) Приоритет Источник Главы / разделы ★★★ Ионетт Дакетт «HTML и CSS» гл. 1–6 ★★★ MDN Learn HTML весь трек ★★ web.dev Learn HTML семантика, формы ★★ Scott Chacon «Pro Git» гл. 1–2 — основы и коммиты ★ HTML5 Doctor (архив) семантические элементы ★ A11y Project Checklist доступность День 0 (до понедельника): Git и GitHub — подготовка Время (полный): ~55м теория · ~1.5ч практика · ~1…"} \ No newline at end of file diff --git a/docs/weeks/02.json b/docs/weeks/02.json index 053b9eb..8f5860e 100644 --- a/docs/weeks/02.json +++ b/docs/weeks/02.json @@ -1 +1 @@ -{"id": "week-02", "title": "CSS основы", "fullTitle": "Неделя 2: CSS — селекторы, box model, типографика, переменные", "html": "

                                                                                                                                                                                                                        Неделя 2: CSS — селекторы, box model, типографика, переменные

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: освоить фундамент CSS — от селекторов до типографики и кастомных свойств.\nЛитература: Ионетт Дакетт «HTML и CSS» (гл. 10–13), web.dev Learn CSS, CSS Reference, Every Layout — паттерны без «магических» хаков

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md\nGit: минимум 1 осмысленный коммит каждый день в learning-log/week-02/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Подключение CSS и селекторы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Styled Blog Post

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CSS (Cascading Style Sheets) отделяет оформление от структуры HTML. Подключить стили можно тремя способами: inline-атрибут style (плохо для поддержки), блок <style> в <head> (допустимо для прототипа) и внешний файл .css через <link rel=\"stylesheet\"> — предпочтительный вариант: один файл кэшируется браузером и обслуживает все страницы сайта.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Селектор — это «адрес» элементов, к которым применится правило. Базовые типы: по тегу (p), по классу (.card), по id (#header), по атрибуту ([type=\"email\"]), универсальный (*). Комбинаторы уточняют связь: потомок (пробел — любой уровень вложенности), дочерний (> — только прямой ребёнок), соседний (+) и общий сосед (~). Псевдоклассы (:hover, :focus, :nth-child()) реагируют на состояние; псевдоэлементы (::before, ::after) создают виртуальные узлы — но без свойства content они не появятся на экране.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Селектор по классу предпочтительнее #id: классы переиспользуются, id уникален и повышает специфичность, делая CSS хрупким. :not() сужает выборку элегантно: li:not(:last-child) вместо ручных классов на каждый элемент.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: внешний CSS + селекторы по классу — основа поддерживаемых стилей.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: CSS first steps — inline, <style>, внешний файл

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай styles.css и подключи к HTML из недели 1
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Стилизуй навигацию: базовый вид, :hover, :focus-visible
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Чередуй фон строк в списке через :nth-child(even)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Добавь декоративный ::before к заголовкам секций
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. В DevTools поэкспериментируй с селекторами в панели Styles
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь селектор [aria-current=\"page\"] для активного пункта навигации
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь, что все интерактивные элементы имеют видимый :focus-visible
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] CSS вынесен во внешний файл, нет inline-стилей в HTML\n- [ ] Использованы минимум 3 типа селекторов\n- [ ] Состояния :hover и :focus-visible различимы

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай styles.css и подключи к HTML из недели 1
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Стилизуй навигацию: базовый вид, :hover, :focus-visible
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Чередуй фон строк в списке через :nth-child(even)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Добавь декоративный ::before к заголовкам секций
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 02 day 1: css selectors and nav styles\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Каскад, специфичность и наследование

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Styled Blog Post

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слово «каскад» в CSS — ключ к пониманию, почему одно свойство иногда «не работает». Когда несколько правил нацелены на один элемент, браузер выбирает победителя в три этапа: важность (!important), специфичность селектора, порядок в файле (последний при равной специфичности). Специфичность считается как веса: inline-стиль > id > class/атрибут/псевдокласс > элемент/псевдоэлемент. Цепочка #nav .item a:hover тяжелее, чем .link — и перебьёт его, даже если написана раньше.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Наследование распространяет некоторые свойства от родителя к детям: color, font-family, line-height. Другие — margin, padding, border — не наследуются; каждый элемент начинает с нуля. Задай font-family на body, и весь текст унаследует шрифт. Ключевые слова inherit, initial, unset и revert управляют этим явно: inherit берёт значение родителя, initial — дефолт спецификации, revert — стиль браузера по умолчанию.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Высокая специфичность — ловушка: добавить новое правило становится сложно без !important, а это запускает «войну важности». Цель — писать селекторы минимальной достаточной силы, обычно на уровне одного-двух классов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: каскад — не баг, а механизм разрешения конфликтов; специфичность — его валюта.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Cascade and inheritance

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай конфликт специфичности: стилизуй p тремя способами, предскажи результат
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Проверь предсказание в браузере, зафиксируй в комментарии CSS
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Используй inherit для единообразия цвета ссылок внутри footer
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Убери лишние !important если появились — перепиши селекторы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Изучи Computed styles в DevTools для одного элемента
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Вычисли специфичность трёх своих селекторов вручную и сверь с DevTools
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Перепиши один конфликтный блок, снизив специфичность до одного класса
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Могу объяснить, какое правило победит в конфликте\n- [ ] Нет !important без веской причины\n- [ ] Наследование используется осознанно

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай конфликт специфичности: стилизуй p тремя способами, предскажи результат
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Проверь предсказание в браузере, зафиксируй в комментарии CSS
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Используй inherit для единообразия цвета ссылок внутри footer
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Убери лишние !important если появились — перепиши селекторы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 02 day 2: cascade and specificity\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Война специфичности: цепочки #id .class div span — признак плохого CSS
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • !important лечит симптом, не причину
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Стилизация через ID — хрупко при рефакторинге
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): Box Model

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Styled Blog Post

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Каждый HTML-элемент в CSS — прямоугольная коробка. Боксовая модель описывает её слои, изнутри наружу: content (текст и картинки) → padding (внутренний отступ) → border (рамка) → margin (внешний отступ до соседей). Представь подарочную коробку: содержимое, мягкая подложка, обёртка и расстояние до других коробок на полке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        По умолчанию box-sizing: content-box: свойства width и height задают только content, а padding и border добавляются сверху. Карточка width: 300px с padding: 20px и border: 2px займёт 344px — сюрприз для сетки. Глобальный сброс box-sizing: border-box включает padding и border в заявленную ширину — предсказуемая вёрстка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Margin collapse — особенность блочной вёрстки: вертикальные margin соседних блоков схлопываются в один (больший), а не складываются. Два блока с margin-bottom: 30px и margin-top: 20px разойдутся на 30px, не на 50. Горизонтальные margin не схлопываются. display: inline элементы игнорируют width/height; для кнопок и бейджей чаще нужен inline-block.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: border-box + понимание margin collapse = контроль над размерами без магии.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Box model

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Нарисуй на бумаге box model для карточки, затем сверстай её
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Примени box-sizing: border-box глобально через *, *::before, *::after
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай три карточки с одинаковой шириной, разным padding — проверь выравнивание
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Продемонстрируй margin collapse двумя блоками с вертикальными отступами
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. В DevTools включи overlay box model для визуализации
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Исправь «ломающийся» блок с overflow — сравни hidden vs auto
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Сверстай горизонтальный ряд inline-block элементов с vertical-align
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] border-box подключён глобально\n- [ ] Карточки визуально одинаковой ширины при разном padding\n- [ ] Понимаю разницу inline vs inline-block

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Нарисуй на бумаге box model для карточки, затем сверстай её
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Примени box-sizing: border-box глобально через *, *::before, *::after
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай три карточки с одинаковой шириной, разным padding — проверь выравнивание
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Продемонстрируй margin collapse двумя блоками с вертикальными отступами
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 02 day 3: box model and cards\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): Типографика и текст

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Styled Blog Post

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Типографика — 90% того, что пользователь читает на сайте. Шрифт задаётся стеком font-family: 'Inter', system-ui, sans-serif — браузер берёт первый доступный. font-size и font-weight строят иерархию заголовков; line-height (межстрочный интервал) критичен для комфорта: для body-текста 1.5–1.7 — золотая середина.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Длина строки влияет на читаемость сильнее, чем кажется. Оптимум — 45–75 символов; длинные строки заставляют глаз терять начало следующей. Ограничь текст max-width: 65ch — единица ch равна ширине символа «0» текущего шрифта. Веб-шрифты подключают через @font-face или сервисы вроде Google Fonts; font-display: swap показывает системный шрифт, пока кастомный грузится — меньше «невидимого текста» (FOIT).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Вертикальный ритм — согласованные отступы, кратные line-height. Если базовый интервал 1.6 × 16px = 25.6px, отступы между абзацами логично делать кратными этому значению. Свойства letter-spacing, text-transform и text-decoration — тонкая настройка, не злоупотребляй: уменьшенный letter-spacing на мобильном ухудшает читаемость.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: типографика — не украшение, а инженерия читаемости; ch и line-height важнее декоративных шрифтов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Typography\n- web.dev: Learn Typography — вертикальный ритм

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи пару шрифтов (заголовки + текст) через Google Fonts
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Задай базовый font-size: 16px, line-height: 1.6 для body
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Настрой иерархию заголовков: размер, вес, отступы
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Ограничь ширину текстового блока max-width: 65ch для читаемости
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Стилизуй цитату: blockquote, курсив, левая граница
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь font-feature-settings или text-rendering для заголовков (эксперимент)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь читаемость на мобильном — уменьши letter-spacing при необходимости
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Текст читаем на мобильном и десктопе\n- [ ] Не более 2–3 семейств шрифтов на странице\n- [ ] line-height задан для основного текста

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи пару шрифтов (заголовки + текст) через Google Fonts
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Задай базовый font-size: 16px, line-height: 1.6 для body
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Настрой иерархию заголовков: размер, вес, отступы
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Ограничь ширину текстового блока max-width: 65ch для читаемости
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 02 day 4: typography and fonts\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Цвета, фоны и тени

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Styled Blog Post

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цвет в CSS — не только эстетика, но и доступность. Форматы: hex (#3366cc), rgb(), hsl(), современный oklch(). HSL и OKLCH удобны для вариаций: меняешь только lightness, сохраняя оттенок — получаешь палитру hover/active из одного базового цвета.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Фоны выходят за сплошную заливку: background-image с linear-gradient создаёт hero-секции без тяжёлых картинок; background-size: cover масштабирует изображение на весь блок. Тени (box-shadow) и скругления (border-radius) добавляют глубину карточкам. Важный нюанс: opacity: 0.5 на родителе делает полупрозрачными всех детей; для полупрозрачного фона без влияния на текст используй rgba() или hsla().

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        box-shadow рисует тень прямоугольника элемента; filter: drop-shadow() следует за альфа-каналом PNG — лучше для иконок с прозрачностью. Всегда проверяй контраст текста на фоне: WCAG AA требует 4.5:1 для обычного текста, иначе градиент «съедает» читаемость.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: rgba для полупрозрачного фона, opacity — когда прозрачным должен быть весь блок целиком.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN color

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай hero-секцию с градиентным фоном и полупрозрачным оверлеем
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Стилизуй кнопки: обычное, hover, active состояния с плавным переходом цвета
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь карточкам border-radius и лёгкую box-shadow
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь контраст текста на фоне (минимум 4.5:1 для обычного текста)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Сделай тёмный вариант hero через другой градиент (подготовка к переменным)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сравни opacity: 0.5 на блоке vs background: rgba(..., 0.5) — зафиксируй разницу
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь :active состояние с transform: scale(0.98) для тактильного отклика
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Контраст текста соответствует WCAG AA\n- [ ] Градиент не мешает читаемости\n- [ ] Кнопки имеют distinct states

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай hero-секцию с градиентным фоном и полупрозрачным оверлеем
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Стилизуй кнопки: обычное, hover, active состояния с плавным переходом цвета
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь карточкам border-radius и лёгкую box-shadow
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь контраст текста на фоне (минимум 4.5:1 для обычного текста)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 02 day 5: colors backgrounds shadows\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): CSS-переменные (Custom Properties)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Styled Blog Post

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CSS Custom Properties (переменные) — нативный механизм темизации без препроцессоров. Объявляются с двойным дефисом: --color-primary: #3366cc, обычно в :root (псевдокласс корня документа). Используются через var(--color-primary, #000) — второй аргумент fallback на случай отсутствия переменной.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Главное отличие от Sass $variables: CSS-переменные живут в runtime. Их можно менять через JavaScript (element.style.setProperty), media queries и классы на html. Переменные наследуются по DOM: задай токены в :root, переопредели в .theme-dark — все дочерние элементы подхватят новые значения. Тёмная тема через переопределение токенов чище, чем дублирование сотен правил.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Design tokens — именованные константы дизайн-системы: --spacing-md, --radius-lg, --color-text. Один источник правды: дизайнер меняет токен — обновляется весь интерфейс. Это мост между дизайном в Figma и кодом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: CSS-переменные — живые токены, которые наследуются и меняются в runtime.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Using CSS custom properties

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Вынеси палитру в :root: primary, secondary, text, bg, border
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Переведи все цвета страницы на var(--...)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай класс .theme-dark с переопределением переменных в html или body
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Добавь кнопку переключения темы (пока через класс на html, без JS — второй HTML-файл)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Задай --spacing-sm/md/lg и используй для отступов
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь токены --radius-sm/md/lg и примени к карточкам и кнопкам
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь, что при удалении одной переменной fallback срабатывает корректно
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Нет «магических» hex-значений вне :root\n- [ ] Тёмная тема работает через переопределение переменных\n- [ ] Есть fallback у критичных var()

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Вынеси палитру в :root: primary, secondary, text, bg, border
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Переведи все цвета страницы на var(--...)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай класс .theme-dark с переопределением переменных в html или body
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Добавь кнопку переключения темы (пока через класс на html, без JS — второй HTML-файл)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 02 day 6: css custom properties\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Единицы измерения и финальная стилизация

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Styled Blog Post

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Единицы измерения в CSS делятся на абсолютные и относительные. px — фиксированный пиксель, предсказуем, но не масштабируется с настройками пользователя. rem привязан к font-size элемента html (обычно 16px): 1.5rem = 24px при базе 16. Измени font-size на html — весь интерфейс пропорционально вырастет. em привязан к font-size родителя — во вложенных элементах может неожиданно «раздуваться».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        % — доля от родителя; vw/vh — процент viewport; ch — ширина символа «0», идеален для max-width текстовых колонок. Функция clamp(min, preferred, max) даёт fluid typography без media queries: clamp(1.5rem, 4vw, 3rem) — заголовок плавно растёт между мобильным и десктопом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Правило: font-size и spacing — в rem; em — для локальных отступов относительно компонента (padding кнопки); px — для тонких границ (border: 1px).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: rem для масштабируемости, clamp() для плавной адаптивности без десятка breakpoints.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: CSS values and units

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Переведи все font-size на rem (база 16px в html)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Отступы секций задай через rem или spacing-переменные
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Заголовок hero сделай через clamp(1.5rem, 4vw, 3rem)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Полностью стилизуй лендинг недели 1 — он должен выглядеть профессионально
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Прогони Lighthouse Best Practices и исправь замечания
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Проверь масштабирование: увеличь font-size на html до 20px — всё должно пропорционально вырасти
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Создай week-02/ с блог-постом — финальная сборка проекта недели
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Размеры шрифтов в rem, не в произвольных px\n- [ ] Страница выглядит цельно: палитра, типографика, отступы\n- [ ] Lighthouse Performance ≥ 85 на статике

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Переведи все font-size на rem (база 16px в html)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Отступы секций задай через rem или spacing-переменные
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Заголовок hero сделай через clamp(1.5rem, 4vw, 3rem)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Полностью стилизуй лендинг недели 1 — он должен выглядеть профессионально
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 02 day 7: rem clamp final styling\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Стилизованный блог-пост — одна HTML-страница статьи с богатой типографикой и дизайн-системой на CSS-переменных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подробное описание: docs/projects.md — Неделя 2

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Требования:\n- Дизайн-токены в :root (цвета, шрифты, spacing, radius)\n- Hero, article body, sidebar, footer; card-компонент для «похожих статей»\n- Тёмная тема через класс и переменные\n- clamp() для заголовка, max-width: 65ch для текста

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] Единая система переменных, нет разбросанных литералов\n- [ ] Контраст и типографика на уровне профессионального блога\n- [ ] Адаптивность базового уровня (читаемо на 375px)\n- [ ] Код CSS структурирован комментариями по секциям\n- [ ] Папка week-02/ в learning-log с README и скриншотом\n- [ ] Ветка feature/dark-theme смержена в main, тег week-02-done\n- [ ] Sidebar и карточки «похожих статей» используют общие токены spacing/radius\n- [ ] Переключение тёмной темы меняет только переменные, не дублирует правила\n- [ ] Lighthouse Accessibility ≥ 90, контраст текста WCAG AA

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Могу ли я вычислить специфичность селектора #nav .item a:hover?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • В чём разница content-box и border-box?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Почему для font-size предпочтительнее rem, а не px?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как переопределить CSS-переменную для дочернего элемента?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Могу ли я объяснить каскад без обращения к документации?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Styled Blog Post** в `learning-log/week-02/`, осмысленная Git-история, тег `week-02-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nCSS: селекторы, box model, типографика, design tokens\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-02-day-1", "label": "День 1 (Mon): Подключение CSS и селекторы"}, {"id": "week-02-day-2", "label": "День 2 (Tue): Каскад, специфичность и наследование"}, {"id": "week-02-day-3", "label": "День 3 (Wed): Box Model"}, {"id": "week-02-day-4", "label": "День 4 (Thu): Типографика и текст"}, {"id": "week-02-day-5", "label": "День 5 (Fri): Цвета, фоны и тени"}, {"id": "week-02-day-6", "label": "День 6 (Sat): CSS-переменные (Custom Properties)"}, {"id": "week-02-day-7", "label": "День 7 (Sun): Единицы измерения и финальная стилизация"}, {"id": "week-02-project", "label": "Проект недели"}, {"id": "week-02-review", "label": "Ревью-чеклист"}], "text": "Неделя 2: CSS — селекторы, box model, типографика, переменные Цель недели: освоить фундамент CSS — от селекторов до типографики и кастомных свойств. Литература: Ионетт Дакетт «HTML и CSS» (гл. 10–13), web.dev Learn CSS , CSS Reference , Every Layout — паттерны без «магических» хаков Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-02/ День 1 (Mon): Подключение CSS и селекторы Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Styled Blog Post Теория CSS (Cascading Style Sheets) отделяет оформление от структуры HTML. Подключить стили можно тремя способами: inline-атрибут style (плохо для поддержки), блок <style> в <head> (допусти…"} \ No newline at end of file +{"id": "week-02", "title": "CSS основы", "fullTitle": "Неделя 2: CSS — селекторы, box model, типографика, переменные", "html": "

                                                                                                                                                                                                                        Неделя 2: CSS — селекторы, box model, типографика, переменные

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: освоить фундамент CSS — от селекторов до типографики и кастомных свойств.\nЛитература: Ионетт Дакетт «HTML и CSS» (гл. 10–13), web.dev Learn CSS, CSS Reference, Every Layout — паттерны без «магических» хаков

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md\nGit: минимум 1 осмысленный коммит каждый день в learning-log/week-02/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Подключение CSS и селекторы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Styled Blog Post

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CSS (Cascading Style Sheets) отделяет оформление от структуры HTML. Подключить стили можно тремя способами: inline-атрибут style (плохо для поддержки), блок <style> в <head> (допустимо для прототипа) и внешний файл .css через <link rel=\"stylesheet\"> — предпочтительный вариант: один файл кэшируется браузером и обслуживает все страницы сайта.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Селектор — это «адрес» элементов, к которым применится правило. Базовые типы: по тегу (p), по классу (.card), по id (#header), по атрибуту ([type=\"email\"]), универсальный (*). Комбинаторы уточняют связь: потомок (пробел — любой уровень вложенности), дочерний (> — только прямой ребёнок), соседний (+) и общий сосед (~). Псевдоклассы (:hover, :focus, :nth-child()) реагируют на состояние; псевдоэлементы (::before, ::after) создают виртуальные узлы — но без свойства content они не появятся на экране.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Селектор по классу предпочтительнее #id: классы переиспользуются, id уникален и повышает специфичность, делая CSS хрупким. :not() сужает выборку элегантно: li:not(:last-child) вместо ручных классов на каждый элемент.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель: HTML прошлой недели — это здание без покраски, а CSS — маляр, который приходит и красит стены, не трогая саму конструкцию. Селекторы — это адрес: «покрась именно эти стены», и чем точнее адрес, тем меньше риск покрасить что-то лишнее по ошибке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: селекторы — язык, на котором ты будешь разговаривать с DOM всю оставшуюся программу. На неделе 6 в JavaScript document.querySelector('.card:not(.hidden)') использует ровно тот же синтаксис CSS-селекторов; во фреймворках (React, Vue) CSS-модули и styled-components тоже строятся вокруг классов, а не id. Плохая привычка навешивать #id на всё сегодня аукнется путаницей в компонентном коде позже.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: чтобы стилизовать активный пункт меню, соблазн — дать ему id=\"active\". Но если пункт меняется в зависимости от страницы (через JS или атрибут aria-current=\"page\"), гораздо гибче написать .nav-link[aria-current=\"page\"] — один селектор работает на любой странице сайта без дублирования id.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение новичков — думать, что раз id «более специфичный», значит «более правильный» выбор по умолчанию. На деле высокая специфичность id — это недостаток, а не достоинство: она мешает переопределить стиль позже без !important. Правильная стратегия — начинать с классов и повышать специфичность только когда есть явная причина.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: внешний CSS + селекторы по классу — основа поддерживаемых стилей, и сегодняшняя практика с :hover/:focus-visible/:nth-child() — это тренировка думать в терминах «состояние + класс», а не «id под каждый частный случай».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: CSS first steps — inline, <style>, внешний файл

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай styles.css и подключи к HTML из недели 1
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Стилизуй навигацию: базовый вид, :hover, :focus-visible
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Чередуй фон строк в списке через :nth-child(even)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Добавь декоративный ::before к заголовкам секций
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. В DevTools поэкспериментируй с селекторами в панели Styles
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь селектор [aria-current=\"page\"] для активного пункта навигации
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь, что все интерактивные элементы имеют видимый :focus-visible
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] CSS вынесен во внешний файл, нет inline-стилей в HTML\n- [ ] Использованы минимум 3 типа селекторов\n- [ ] Состояния :hover и :focus-visible различимы

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай styles.css и подключи к HTML из недели 1
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Стилизуй навигацию: базовый вид, :hover, :focus-visible
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Чередуй фон строк в списке через :nth-child(even)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Добавь декоративный ::before к заголовкам секций
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 02 day 1: css selectors and nav styles\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Каскад, специфичность и наследование

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Styled Blog Post

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слово «каскад» в CSS — ключ к пониманию, почему одно свойство иногда «не работает». Когда несколько правил нацелены на один элемент, браузер выбирает победителя в три этапа: важность (!important), специфичность селектора, порядок в файле (последний при равной специфичности). Специфичность считается как веса: inline-стиль > id > class/атрибут/псевдокласс > элемент/псевдоэлемент. Цепочка #nav .item a:hover тяжелее, чем .link — и перебьёт его, даже если написана раньше.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Наследование распространяет некоторые свойства от родителя к детям: color, font-family, line-height. Другие — margin, padding, border — не наследуются; каждый элемент начинает с нуля. Задай font-family на body, и весь текст унаследует шрифт. Ключевые слова inherit, initial, unset и revert управляют этим явно: inherit берёт значение родителя, initial — дефолт спецификации, revert — стиль браузера по умолчанию.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Высокая специфичность — ловушка: добавить новое правило становится сложно без !important, а это запускает «войну важности». Цель — писать селекторы минимальной достаточной силы, обычно на уровне одного-двух классов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель: каскад — это не хаос, а суд с чётким регламентом. Три этапа разрешения конфликта (важность → специфичность → порядок) — это последовательность вопросов судьи: сначала «есть ли !important?», потом «чей селектор точнее?», и только при ничьей — «кто выступил последним?». Если понимать эту последовательность, «CSS не работает» перестаёт быть загадкой и превращается в задачу с однозначным ответом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: специфичность и каскад будут влиять на любой CSS до конца обучения — и на неделе 3 с Flexbox/Grid, и в CSS-модулях React, и при подключении сторонних библиотек (Bootstrap, Tailwind), стили которых нужно будет переопределять осознанно, а не случайным !important. Чем раньше выработается привычка вычислять специфичность в уме, тем меньше часов будет потрачено на отладку «почему стиль не применяется» в будущем.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: .button { color: blue; } и #submit-btn { color: red; } конкурируют за один и тот же элемент — при равном порядке победит id-селектор просто в силу более высокого веса, даже если правило с классом идёт ниже в файле. Добавление к кнопке класса .button--primary { color: green; } тоже проиграет id, пока специфичность id не будет снижена или селектор класса не станет точнее.

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: каскад — не баг, а механизм разрешения конфликтов; специфичность — его валюта, и сегодняшняя практика с ручным вычислением специфичности трёх селекторов — тренировка читать эту «валюту» без обращения к DevTools.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Cascade and inheritance

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай конфликт специфичности: стилизуй p тремя способами, предскажи результат
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Проверь предсказание в браузере, зафиксируй в комментарии CSS
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Используй inherit для единообразия цвета ссылок внутри footer
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Убери лишние !important если появились — перепиши селекторы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Изучи Computed styles в DevTools для одного элемента
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Вычисли специфичность трёх своих селекторов вручную и сверь с DevTools
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Перепиши один конфликтный блок, снизив специфичность до одного класса
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Могу объяснить, какое правило победит в конфликте\n- [ ] Нет !important без веской причины\n- [ ] Наследование используется осознанно

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай конфликт специфичности: стилизуй p тремя способами, предскажи результат
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Проверь предсказание в браузере, зафиксируй в комментарии CSS
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Используй inherit для единообразия цвета ссылок внутри footer
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Убери лишние !important если появились — перепиши селекторы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 02 day 2: cascade and specificity\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Война специфичности: цепочки #id .class div span — признак плохого CSS
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • !important лечит симптом, не причину
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Стилизация через ID — хрупко при рефакторинге
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): Box Model

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Styled Blog Post

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Каждый HTML-элемент в CSS — прямоугольная коробка. Боксовая модель описывает её слои, изнутри наружу: content (текст и картинки) → padding (внутренний отступ) → border (рамка) → margin (внешний отступ до соседей). Представь подарочную коробку: содержимое, мягкая подложка, обёртка и расстояние до других коробок на полке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        По умолчанию box-sizing: content-box: свойства width и height задают только content, а padding и border добавляются сверху. Карточка width: 300px с padding: 20px и border: 2px займёт 344px — сюрприз для сетки. Глобальный сброс box-sizing: border-box включает padding и border в заявленную ширину — предсказуемая вёрстка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Margin collapse — особенность блочной вёрстки: вертикальные margin соседних блоков схлопываются в один (больший), а не складываются. Два блока с margin-bottom: 30px и margin-top: 20px разойдутся на 30px, не на 50. Горизонтальные margin не схлопываются. display: inline элементы игнорируют width/height; для кнопок и бейджей чаще нужен inline-block.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Абсолютно каждый элемент на странице — прямоугольник, даже если визуально выглядит круглым или невидимым; это стоит держать в голове как базовый факт CSS-мышления. Умение «включить» в голове границы коробок вокруг любого элемента страницы — по сути, главный навык отладки вёрстки, который пригодится до конца обучения: в DevTools эта модель визуализируется буквально теми же четырьмя слоями.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это критично дальше: на неделе 3 Flexbox и Grid распределяют именно эти коробки по осям — без понимания, где заканчивается content и начинается margin, предсказать поведение сетки невозможно. Разработчики годами спорят о content-box vs border-box именно потому, что путаница в размерах — причина большинства «съехавших» макетов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: три карточки в ряд по width: 33.33% с content-box и padding: 20px каждая окажутся шире контейнера в сумме и перенесутся на новую строку — визуально «сетка сломалась» без единой ошибки в разметке. С border-box та же конструкция работает как ожидается, потому что padding вычитается из заявленных 33.33%, а не добавляется поверх.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение новичков — путать margin collapse с багом браузера, когда два блока с суммарными отступами 50px визуально расходятся только на 30px. Это ожидаемое поведение спецификации CSS для смежных вертикальных margin блочных элементов — оно не работает для padding, border, горизонтальных margin или элементов с display: flex/grid в качестве родителя.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: border-box + понимание margin collapse = контроль над размерами без магии, а не жонглирование случайными пикселями до тех пор, пока «не встанет на место».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Box model

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Нарисуй на бумаге box model для карточки, затем сверстай её
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Примени box-sizing: border-box глобально через *, *::before, *::after
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай три карточки с одинаковой шириной, разным padding — проверь выравнивание
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Продемонстрируй margin collapse двумя блоками с вертикальными отступами
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. В DevTools включи overlay box model для визуализации
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Исправь «ломающийся» блок с overflow — сравни hidden vs auto
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Сверстай горизонтальный ряд inline-block элементов с vertical-align
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] border-box подключён глобально\n- [ ] Карточки визуально одинаковой ширины при разном padding\n- [ ] Понимаю разницу inline vs inline-block

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Нарисуй на бумаге box model для карточки, затем сверстай её
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Примени box-sizing: border-box глобально через *, *::before, *::after
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай три карточки с одинаковой шириной, разным padding — проверь выравнивание
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Продемонстрируй margin collapse двумя блоками с вертикальными отступами
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 02 day 3: box model and cards\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): Типографика и текст

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Styled Blog Post

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Типографика — 90% того, что пользователь читает на сайте. Шрифт задаётся стеком font-family: 'Inter', system-ui, sans-serif — браузер берёт первый доступный. font-size и font-weight строят иерархию заголовков; line-height (межстрочный интервал) критичен для комфорта: для body-текста 1.5–1.7 — золотая середина.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Длина строки влияет на читаемость сильнее, чем кажется. Оптимум — 45–75 символов; длинные строки заставляют глаз терять начало следующей. Ограничь текст max-width: 65ch — единица ch равна ширине символа «0» текущего шрифта. Веб-шрифты подключают через @font-face или сервисы вроде Google Fonts; font-display: swap показывает системный шрифт, пока кастомный грузится — меньше «невидимого текста» (FOIT).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Вертикальный ритм — согласованные отступы, кратные line-height. Если базовый интервал 1.6 × 16px = 25.6px, отступы между абзацами логично делать кратными этому значению. Свойства letter-spacing, text-transform и text-decoration — тонкая настройка, не злоупотребляй: уменьшенный letter-spacing на мобильном ухудшает читаемость.

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: типографика — тот редкий навык CSS, который напрямую конвертируется в конверсию и удержание пользователей на реальных проектах; на неделе 3 при вёрстке SaaS-лендинга и позже в любых проектах именно читаемость текста будет определять, дочитает ли посетитель страницу до кнопки CTA или уйдёт раньше. Плохая типографика не «ломает» сайт визуально, но незаметно снижает эффективность всего остального дизайна.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: одна и та же статья с line-height: 1.2 и max-width: 100% (растянутая на весь экран 1920px) читается тяжело — строка в 200+ символов заставляет глаз «терять» начало следующей строки при возврате. Та же статья с line-height: 1.6 и max-width: 65ch превращается в комфортный блок текста, похожий на хорошо свёрстанную книгу.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение новичков — подбирать line-height и размеры «на глаз, пока не станет красиво», не привязываясь к базовому масштабу. Без системы (например, кратности вертикального ритма) отступы между разными блоками страницы начинают визуально не совпадать друг с другом, даже если каждый по отдельности выглядит нормально.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: типографика — не украшение, а инженерия читаемости; ch и line-height важнее декоративных шрифтов, а сегодняшняя практика с ограничением ширины текста в 65ch — первый шаг к этой дисциплине.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Typography\n- web.dev: Learn Typography — вертикальный ритм

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи пару шрифтов (заголовки + текст) через Google Fonts
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Задай базовый font-size: 16px, line-height: 1.6 для body
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Настрой иерархию заголовков: размер, вес, отступы
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Ограничь ширину текстового блока max-width: 65ch для читаемости
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Стилизуй цитату: blockquote, курсив, левая граница
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь font-feature-settings или text-rendering для заголовков (эксперимент)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь читаемость на мобильном — уменьши letter-spacing при необходимости
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Текст читаем на мобильном и десктопе\n- [ ] Не более 2–3 семейств шрифтов на странице\n- [ ] line-height задан для основного текста

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи пару шрифтов (заголовки + текст) через Google Fonts
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Задай базовый font-size: 16px, line-height: 1.6 для body
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Настрой иерархию заголовков: размер, вес, отступы
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Ограничь ширину текстового блока max-width: 65ch для читаемости
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 02 day 4: typography and fonts\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Цвета, фоны и тени

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Styled Blog Post

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цвет в CSS — не только эстетика, но и доступность. Форматы: hex (#3366cc), rgb(), hsl(), современный oklch(). HSL и OKLCH удобны для вариаций: меняешь только lightness, сохраняя оттенок — получаешь палитру hover/active из одного базового цвета.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Фоны выходят за сплошную заливку: background-image с linear-gradient создаёт hero-секции без тяжёлых картинок; background-size: cover масштабирует изображение на весь блок. Тени (box-shadow) и скругления (border-radius) добавляют глубину карточкам. Важный нюанс: opacity: 0.5 на родителе делает полупрозрачными всех детей; для полупрозрачного фона без влияния на текст используй rgba() или hsla().

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        box-shadow рисует тень прямоугольника элемента; filter: drop-shadow() следует за альфа-каналом PNG — лучше для иконок с прозрачностью. Всегда проверяй контраст текста на фоне: WCAG AA требует 4.5:1 для обычного текста, иначе градиент «съедает» читаемость.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель: думай о цвете не как о наборе разрозненных hex-кодов, а как о палитре с системой — базовый оттенок и его вариации по яркости, как краски художника, смешанные из одной тюбика с добавлением белого или чёрного. HSL/OKLCH делают эту систему явной в коде: меняя только один параметр (lightness), получаешь согласованный набор состояний вместо угадывания «какой ещё синий взять для hover».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: завтра, в день 6, ты вынесешь именно эти цвета в CSS-переменные — и то, насколько системно они организованы сегодня (базовый + вариации, а не 15 несвязанных hex-кодов), определит, насколько легко будет собрать тёмную тему завтра. Хаотичная палитра сегодня означает мучительный рефакторинг завтра.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: hero-секция с background: linear-gradient(135deg, #1a1a2e, #16213e) и белым текстом поверх может визуально понравиться, но если не проверить контраст в месте, где текст пересекает более светлую часть градиента, там текст может провалиться ниже 4.5:1 — форматально «одна и та же секция» в разных точках имеет разный контраст.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать opacity универсальным способом сделать элемент «полупрозрачным». opacity: 0.5 на карточке с текстом сделает бледным и текст, и рамку, и фон одновременно — а часто нужно затемнить только фон, оставив текст чётким. Для этого — rgba()/hsla() именно на свойстве background, а не opacity на всём блоке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: rgba для полупрозрачного фона, opacity — когда прозрачным должен быть весь блок целиком, а системная палитра сегодня — фундамент для темизации завтра.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN color

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай hero-секцию с градиентным фоном и полупрозрачным оверлеем
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Стилизуй кнопки: обычное, hover, active состояния с плавным переходом цвета
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь карточкам border-radius и лёгкую box-shadow
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь контраст текста на фоне (минимум 4.5:1 для обычного текста)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Сделай тёмный вариант hero через другой градиент (подготовка к переменным)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сравни opacity: 0.5 на блоке vs background: rgba(..., 0.5) — зафиксируй разницу
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь :active состояние с transform: scale(0.98) для тактильного отклика
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Контраст текста соответствует WCAG AA\n- [ ] Градиент не мешает читаемости\n- [ ] Кнопки имеют distinct states

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай hero-секцию с градиентным фоном и полупрозрачным оверлеем
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Стилизуй кнопки: обычное, hover, active состояния с плавным переходом цвета
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь карточкам border-radius и лёгкую box-shadow
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь контраст текста на фоне (минимум 4.5:1 для обычного текста)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 02 day 5: colors backgrounds shadows\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): CSS-переменные (Custom Properties)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Styled Blog Post

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CSS Custom Properties (переменные) — нативный механизм темизации без препроцессоров. Объявляются с двойным дефисом: --color-primary: #3366cc, обычно в :root (псевдокласс корня документа). Используются через var(--color-primary, #000) — второй аргумент fallback на случай отсутствия переменной.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Главное отличие от Sass $variables: CSS-переменные живут в runtime. Их можно менять через JavaScript (element.style.setProperty), media queries и классы на html. Переменные наследуются по DOM: задай токены в :root, переопредели в .theme-dark — все дочерние элементы подхватят новые значения. Тёмная тема через переопределение токенов чище, чем дублирование сотен правил.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Design tokens — именованные константы дизайн-системы: --spacing-md, --radius-lg, --color-text. Один источник правды: дизайнер меняет токен — обновляется весь интерфейс. Это мост между дизайном в Figma и кодом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель: CSS-переменные — это розетки в доме, а не проводка внутри стен. Sass-переменная ($primary) — это провод, впаянный намертво при компиляции: изменить его после сборки нельзя, не пересобрав весь дом заново. CSS custom property — это розетка: воткнул другую «вилку» значения через класс или JS в любой момент, и всё, что подключено к этой розетке, сразу получает новое напряжение — без пересборки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это критично дальше: тема с переключением light/dark, персонализация интерфейса, адаптация под системные настройки пользователя (prefers-color-scheme) — всё это опирается именно на runtime-природу custom properties. На неделях с React/Vue дизайн-токены станут ещё важнее: компонентные библиотеки (MUI, Chakra) построены вокруг похожей идеи именованных токенов, а не разбросанных значений.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: без переменных тёмная тема потребовала бы продублировать каждое правило с цветом (.card { background: white }.dark .card { background: #222 } для каждого компонента). С токенами достаточно переопределить --bg-surface и --text-primary один раз в .theme-dark, и все компоненты, которые уже используют var(--bg-surface), автоматически подхватят новые значения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — путать CSS custom properties с препроцессорными переменными и ожидать, что var() можно использовать в местах, где нужно значение на этапе компиляции (например, в имени media query или в селекторе) — CSS-переменные работают только там, где ожидается значение свойства, и не подставляются в структуру самого правила.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: CSS-переменные — живые токены, которые наследуются и меняются в runtime, и именно поэтому они, а не hex-коды в каждом правиле, — правильный фундамент дизайн-системы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Using CSS custom properties

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Вынеси палитру в :root: primary, secondary, text, bg, border
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Переведи все цвета страницы на var(--...)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай класс .theme-dark с переопределением переменных в html или body
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Добавь кнопку переключения темы (пока через класс на html, без JS — второй HTML-файл)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Задай --spacing-sm/md/lg и используй для отступов
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь токены --radius-sm/md/lg и примени к карточкам и кнопкам
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь, что при удалении одной переменной fallback срабатывает корректно
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Нет «магических» hex-значений вне :root\n- [ ] Тёмная тема работает через переопределение переменных\n- [ ] Есть fallback у критичных var()

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Вынеси палитру в :root: primary, secondary, text, bg, border
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Переведи все цвета страницы на var(--...)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай класс .theme-dark с переопределением переменных в html или body
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Добавь кнопку переключения темы (пока через класс на html, без JS — второй HTML-файл)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 02 day 6: css custom properties\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Единицы измерения и финальная стилизация

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Styled Blog Post

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Единицы измерения в CSS делятся на абсолютные и относительные. px — фиксированный пиксель, предсказуем, но не масштабируется с настройками пользователя. rem привязан к font-size элемента html (обычно 16px): 1.5rem = 24px при базе 16. Измени font-size на html — весь интерфейс пропорционально вырастет. em привязан к font-size родителя — во вложенных элементах может неожиданно «раздуваться».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        % — доля от родителя; vw/vh — процент viewport; ch — ширина символа «0», идеален для max-width текстовых колонок. Функция clamp(min, preferred, max) даёт fluid typography без media queries: clamp(1.5rem, 4vw, 3rem) — заголовок плавно растёт между мобильным и десктопом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Правило: font-size и spacing — в rem; em — для локальных отступов относительно компонента (padding кнопки); px — для тонких границ (border: 1px).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель: px — это линейка с фиксированной длиной, rem — это линейка, которая растягивается или сжимается вместе с базовыми настройками устройства. Пользователь с ослабленным зрением, увеличивший размер шрифта в настройках браузера до 20px, увидит пропорционально увеличенный интерфейс на rem-based вёрстке — и «сломанный», не увеличивающийся текст на px-based.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: неделя 3 целиком построена на адаптивности через Flexbox, Grid и clamp() — без уверенного понимания rem vs em vs vw сегодня, попытки построить fluid-дизайн завтра превратятся в подбор чисел методом тыка. Это последний день недели 2 — именно сегодняшняя финальная стилизация проверяет, насколько цельно всё сложилось: токены, типографика, box model, единицы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: padding: 1em на кнопке с font-size: 1.2rem внутри карточки с увеличенным текстом даст больший отступ, чем такая же кнопка в обычном месте страницы — потому что em считается от текущего, а не корневого размера шрифта. Это иногда используют осознанно (отступы масштабируются вместе с текстом компонента), а иногда — источник необъяснимого «съехавшего» паддинга.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать vw универсальной заменой rem для адаптивного текста. Чистый font-size: 4vw без clamp() на очень широких экранах (4K-мониторы) может дать нечитаемо огромный текст, а на очень узких — нечитаемо мелкий: vw без ограничителей масштабируется линейно и бесконечно, что и решает clamp(min, preferred, max), задавая границы разумного диапазона.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: rem для масштабируемости, clamp() для плавной адаптивности без десятка breakpoints — и то, и другое станет рабочим инструментом уже завтра, на первом дне недели про Flexbox.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: CSS values and units

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Переведи все font-size на rem (база 16px в html)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Отступы секций задай через rem или spacing-переменные
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Заголовок hero сделай через clamp(1.5rem, 4vw, 3rem)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Полностью стилизуй лендинг недели 1 — он должен выглядеть профессионально
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Прогони Lighthouse Best Practices и исправь замечания
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Проверь масштабирование: увеличь font-size на html до 20px — всё должно пропорционально вырасти
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Создай week-02/ с блог-постом — финальная сборка проекта недели
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Размеры шрифтов в rem, не в произвольных px\n- [ ] Страница выглядит цельно: палитра, типографика, отступы\n- [ ] Lighthouse Performance ≥ 85 на статике

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Переведи все font-size на rem (база 16px в html)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Отступы секций задай через rem или spacing-переменные
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Заголовок hero сделай через clamp(1.5rem, 4vw, 3rem)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Полностью стилизуй лендинг недели 1 — он должен выглядеть профессионально
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 02 day 7: rem clamp final styling\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Стилизованный блог-пост — одна HTML-страница статьи с богатой типографикой и дизайн-системой на CSS-переменных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подробное описание: docs/projects.md — Неделя 2

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Требования:\n- Дизайн-токены в :root (цвета, шрифты, spacing, radius)\n- Hero, article body, sidebar, footer; card-компонент для «похожих статей»\n- Тёмная тема через класс и переменные\n- clamp() для заголовка, max-width: 65ch для текста

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] Единая система переменных, нет разбросанных литералов\n- [ ] Контраст и типографика на уровне профессионального блога\n- [ ] Адаптивность базового уровня (читаемо на 375px)\n- [ ] Код CSS структурирован комментариями по секциям\n- [ ] Папка week-02/ в learning-log с README и скриншотом\n- [ ] Ветка feature/dark-theme смержена в main, тег week-02-done\n- [ ] Sidebar и карточки «похожих статей» используют общие токены spacing/radius\n- [ ] Переключение тёмной темы меняет только переменные, не дублирует правила\n- [ ] Lighthouse Accessibility ≥ 90, контраст текста WCAG AA

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Могу ли я вычислить специфичность селектора #nav .item a:hover?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • В чём разница content-box и border-box?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Почему для font-size предпочтительнее rem, а не px?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как переопределить CSS-переменную для дочернего элемента?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Могу ли я объяснить каскад без обращения к документации?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Styled Blog Post** в `learning-log/week-02/`, осмысленная Git-история, тег `week-02-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nCSS: селекторы, box model, типографика, design tokens\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-02-day-1", "label": "День 1 (Mon): Подключение CSS и селекторы"}, {"id": "week-02-day-2", "label": "День 2 (Tue): Каскад, специфичность и наследование"}, {"id": "week-02-day-3", "label": "День 3 (Wed): Box Model"}, {"id": "week-02-day-4", "label": "День 4 (Thu): Типографика и текст"}, {"id": "week-02-day-5", "label": "День 5 (Fri): Цвета, фоны и тени"}, {"id": "week-02-day-6", "label": "День 6 (Sat): CSS-переменные (Custom Properties)"}, {"id": "week-02-day-7", "label": "День 7 (Sun): Единицы измерения и финальная стилизация"}, {"id": "week-02-project", "label": "Проект недели"}, {"id": "week-02-review", "label": "Ревью-чеклист"}], "text": "Неделя 2: CSS — селекторы, box model, типографика, переменные Цель недели: освоить фундамент CSS — от селекторов до типографики и кастомных свойств. Литература: Ионетт Дакетт «HTML и CSS» (гл. 10–13), web.dev Learn CSS , CSS Reference , Every Layout — паттерны без «магических» хаков Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-02/ День 1 (Mon): Подключение CSS и селекторы Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Styled Blog Post Теория CSS (Cascading Style Sheets) отделяет оформление от структуры HTML. Подключить стили можно тремя способами: inline-атрибут style (плохо для поддержки), блок <style> в <head> (допусти…"} \ No newline at end of file diff --git a/docs/weeks/03.json b/docs/weeks/03.json index d33013e..ed4a74a 100644 --- a/docs/weeks/03.json +++ b/docs/weeks/03.json @@ -1 +1 @@ -{"id": "week-03", "title": "CSS layouts", "fullTitle": "Неделя 3: CSS — Flexbox, Grid, адаптив, анимации", "html": "

                                                                                                                                                                                                                        Неделя 3: CSS — Flexbox, Grid, адаптив, анимации

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: научиться строить современные макеты и адаптивные интерфейсы с Flexbox, Grid и анимациями.\nЛитература: Ионетт Дакетт «HTML и CSS» (гл. 12–14), CSS Tricks: Flexbox Guide, CSS Tricks: Grid Guide, web.dev Learn CSS, Every Layout: Sidebar — готовые адаптивные паттерны

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md\nGit: минимум 1 осмысленный коммит каждый день в learning-log/week-03/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Flexbox — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к SaaS Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Flexbox (Flexible Box Layout) решает задачу одномерного выравнивания: элементы в ряд или в колонку. Контейнер с display: flex становится flex-контейнером; прямые дети — flex-элементами. flex-direction задаёт главную ось: row (горизонталь, по умолчанию) или column (вертикаль). justify-content выравнивает по главной оси (space-between, center); align-items — по поперечной. Свойство gap заменяет margin-хаки между элементами — чище и предсказуемее.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        У flex-элементов три рычага размера: flex-grow (как делить свободное место), flex-shrink (как сжиматься) и flex-basis (начальный размер). Сокращение flex: 1 означает flex: 1 1 0% — элемент жадно забирает доступное пространство. По умолчанию align-items: stretch растягивает детей по поперечной оси — карточки в ряду получают одинаковую высоту без фиксированного height.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Flexbox — не замена Grid: он идеален для навигации, тулбаров, центрирования, рядов карточек. Двумерные макеты — задача Grid.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: Flexbox — одна ось, три свойства выравнивания; gap вместо margin между элементами.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Flexbox

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сверстай шапку сайта: логотип слева, навигация справа (justify-content: space-between)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Сделай ряд из 3 карточек одинаковой высоты с align-items: stretch
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Центрируй блок по вертикали и горизонтали через flex на родителе
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Поэкспериментируй с flex-wrap при сужении окна
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Используй Flexbox Froggy — пройди 12+ уровней
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь gap вместо margin между карточками — сравни читаемость CSS
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Попробуй flex-direction: column для мобильной шапки
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Шапка не ломается при 768px ширине\n- [ ] Карточки одной высоты без фиксированного height\n- [ ] Flexbox Froggy пройден

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сверстай шапку сайта: логотип слева, навигация справа (justify-content: space-between)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Сделай ряд из 3 карточек одинаковой высоты с align-items: stretch
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Центрируй блок по вертикали и горизонтали через flex на родителе
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Поэкспериментируй с flex-wrap при сужении окна
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 03 day 1: flexbox basics\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Flexbox — практические паттерны

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к SaaS Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        На практике Flexbox решает повторяющиеся паттерны. Sticky footer: body { min-height: 100vh; display: flex; flex-direction: column } и main { flex: 1 } — основной контент растягивается, подвал прижат к низу viewport даже на короткой странице. Кнопка внизу карточки: flex-column на карточке + margin-top: auto на кнопке — она уезжает вниз, текст выше занимает сколько нужно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Разница flex: 1 1 auto и flex: 1 1 0: первый стартует с естественного размера контента, второй — с нуля и делит место поровну. Ловушка: flex-элемент с длинным текстом не сжимается без min-width: 0 — браузер считает минимальный размер по контенту и ломает ряд.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        order и align-self меняют визуальный порядок и выравнивание отдельного элемента — используй редко. order не меняет tab-order для клавиатуры — риск для доступности.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: margin-top: auto — flex-паттерн «прижать к краю»; min-width: 0 — страховка от переполнения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- CSS Tricks: Flexbox Guide

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Карточка товара: изображение, заголовок, описание, цена, кнопка прижата к низу
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Sticky footer: body как flex-column, main { flex: 1 }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Горизонтальный скролл галереи: flex-wrap: nowrap, overflow-x: auto
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Pagination: ряд кнопок по центру с gap
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг шапки: мобильное меню-иконка (пока без JS — скрытый блок)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь min-width: 0 на карточку с длинным текстом — проверь, что ряд не ломается
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Сверстай card grid на flex с flex-wrap и flex: 1 1 280px
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Кнопка в карточке всегда внизу при разной длине текста\n- [ ] Footer прижат к низу viewport на короткой странице\n- [ ] Галерея скроллится горизонтально на мобильном

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Карточка товара: изображение, заголовок, описание, цена, кнопка прижата к низу
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Sticky footer: body как flex-column, main { flex: 1 }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Горизонтальный скролл галереи: flex-wrap: nowrap, overflow-x: auto
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Pagination: ряд кнопок по центру с gap
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 03 day 2: flexbox patterns\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • flex: 1 на всех детях — не всегда равная ширина, смотри flex-basis
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Забытый min-width: 0 — flex-элемент не сжимается, ломает вёрстку
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Вертикальное центрирование через margin auto вместо flex — устаревший подход
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): CSS Grid — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к SaaS Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CSS Grid — двумерная сетка: строки и колонки одновременно. display: grid на контейнере; grid-template-columns и grid-template-rows задают треки. Единица fr (fraction) делит свободное пространство пропорционально: 1fr 2fr — вторая колонка вдвое шире. repeat(3, 1fr) — три равные колонки; minmax(200px, 1fr) — колонка не уже 200px, но растёт.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Элементы позиционируются через grid-column, grid-row или именованные зоны grid-template-areas. Areas превращают CSS в карту макета: header header / sidebar main / footer footer — читаемо без подсчёта линий. grid-column: span 2 растягивает элемент на две ячейки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Grid vs Flex: grid для страничных макетов, галерей, дашбордов; flex для навигации, рядов кнопок, выравнивания внутри ячейки grid. Часто они работают вместе: grid — скелет страницы, flex — внутри карточки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: Grid — две оси и именованные зоны; fr делит пространство, а не проценты от неизвестной ширины.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Grid Layout

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сетка 3×2 карточек через grid-template-columns: repeat(3, 1fr)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Макет страницы через areas: header, sidebar, main, footer
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Один элемент растяни на 2 колонки (grid-column: span 2)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Пройди Grid Garden — 12+ уровней
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Сравни тот же макет на flex vs grid — запиши вывод
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь minmax(200px, 1fr) в колонки — проверь поведение при сужении
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Нарисуй схему areas на бумаге, затем перенеси в CSS
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Grid Garden пройден\n- [ ] Макет с areas читаем в CSS без HTML-подсказок\n- [ ] Адаптив: при 600px — одна колонка

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сетка 3×2 карточек через grid-template-columns: repeat(3, 1fr)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Макет страницы через areas: header, sidebar, main, footer
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Один элемент растяни на 2 колонки (grid-column: span 2)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Пройди Grid Garden — 12+ уровней
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 03 day 3: css grid basics\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): Grid — продвинутые макеты

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к SaaS Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Продвинутый Grid убирает необходимость в десятках media queries. repeat(auto-fill, minmax(250px, 1fr)) создаёт responsive-сетку: браузер сам считает, сколько колонок влезет. auto-fill оставляет пустые треки, auto-fit схлопывает их — на широком экране карточки растягиваются, а не остаётся пустая колонка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Grid stacking — два элемента в одной ячейке: наложи текст на изображение, задав обоим grid-row: 1; grid-column: 1. Subgrid (где поддерживается) выравнивает вложенные сетки с родительской — карточки в ряду получают согласованные строки заголовков.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Правило выбора: 1D → flex, 2D → grid. Навигация и кнопки — flex; pricing table, features grid, dashboard — grid. Вложенный grid внутри main — sidebar фиксированной ширины, контент на 1fr.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: auto-fill/auto-fit + minmax() — адаптивная сетка без ручных breakpoints.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- CSS Tricks: Grid Guide

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Галерея с grid-template-columns: repeat(auto-fill, minmax(200px, 1fr))
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Dashboard: sidebar 250px, main 1fr, виджеты внутри main — вложенный grid
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Карточка с overlay-текстом поверх изображения (grid stack)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Pinterest-подобная сетка разной высоты (разный grid-row: span N)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг блога недели 2 на grid-layout
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сравни auto-fill и auto-fit на одной сетке — зафиксируй разницу скриншотом
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь subgrid (если браузер поддерживает) или запиши fallback
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Галерея адаптируется без единой media query\n- [ ] Dashboard читаем на 1024px и 375px\n- [ ] Осознанный выбор flex vs grid в каждом блоке

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Галерея с grid-template-columns: repeat(auto-fill, minmax(200px, 1fr))
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Dashboard: sidebar 250px, main 1fr, виджеты внутри main — вложенный grid
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Карточка с overlay-текстом поверх изображения (grid stack)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Pinterest-подобная сетка разной высоты (разный grid-row: span N)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 03 day 4: advanced grid layouts\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Адаптивный дизайн

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к SaaS Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Адаптивный дизайн — не «версия для мобильного», а один интерфейс, плавно подстраивающийся под экран. Подход mobile-first: базовые стили пишутся для узкого экрана (375px), затем @media (min-width: 768px) добавляют возможности для планшета и десктопа. Расширять проще, чем «отрезать» лишнее с десктопной версии.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Breakpoints (480, 768, 1024, 1280px) — не догма, а ориентиры. Breakpoint выбирай там, где ломается контент: навигация не влезает, карточки сжимаются нечитаемо. meta viewport в <head> обязателен: без него мобильный браузер покажет «уменьшенный десктоп».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Относительные единицы (rem, %, vw) и max-width: 100% на изображениях предотвращают горизонтальный скролл. Touch targets на мобильном — минимум 44×44px: пальцу нужна площадь больше, чем точке курсора. Container queries (@container) — следующий уровень: стили от размера контейнера, а не viewport.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: mobile-first + breakpoint по поломке контента, не по модели телефона.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Responsive design

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши стили mobile-first: база 375px, затем 768px, 1024px
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Навигация: горизонтальная на десктопе, вертикальный список на мобильном
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Типографика: уменьши font-size и spacing на мобильном
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Таблица: горизонтальный скролл или card-view на узком экране
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь в DevTools Device Mode минимум 4 размера
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь meta viewport если отсутствует — проверь масштабирование
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Увеличь padding кнопок на мобильном до touch-friendly размеров
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Нет горизонтального скролла на 375px\n- [ ] Touch targets ≥ 44×44px на мобильном\n- [ ] Breakpoints логичны, не «магические» без причины

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши стили mobile-first: база 375px, затем 768px, 1024px
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Навигация: горизонтальная на десктопе, вертикальный список на мобильном
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Типографика: уменьши font-size и spacing на мобильном
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Таблица: горизонтальный скролл или card-view на узком экране
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 03 day 5: responsive mobile-first\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Переходы и анимации

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к SaaS Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CSS-переходы (transition) анимируют изменение свойства от значения A к B: transition: transform 0.2s ease. Указываешь свойство, длительность, функцию времени (ease, ease-in-out, cubic-bezier). Для hover-эффектов и смены состояний — идеальный инструмент.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        @keyframes + animation — для многошаговых анимаций: появление модалки, пульсация skeleton loader, бесконечный спиннер. Переход срабатывает при смене класса; keyframes идут по расписанию независимо.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Производительность: анимируй только transform и opacity — они обрабатываются на GPU и не вызывают reflow всей страницы. Анимация width, height, margin — дорого. Длительность UI-переходов: 150–300ms; дольше кажется тормозным. Обязательно учитывай prefers-reduced-motion: reduce — у пользователей с вестибулярными нарушениями анимации могут вызывать тошноту.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: transition для состояний, @keyframes для сцен; только transform и opacity на проде.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: CSS transitions\n- MDN: CSS animations

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Плавные hover-эффекты на кнопках и карточках (transition: 0.2s ease)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Анимация появления модального блока через @keyframes fadeIn
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Skeleton loader для карточки (пульсирующий градиент)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Оберни анимации в @media (prefers-reduced-motion: no-preference)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Избегай анимации width/height — используй transform и opacity
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь will-change: transform на анимируемый элемент (осторожно, не везде)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Сравни ease, ease-in-out, cubic-bezier — выбери для кнопок
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Анимации на GPU-свойствах (transform, opacity)\n- [ ] prefers-reduced-motion учтён\n- [ ] Переходы не медленнее 300ms для UI-интеракций

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Плавные hover-эффекты на кнопках и карточках (transition: 0.2s ease)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Анимация появления модального блока через @keyframes fadeIn
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Skeleton loader для карточки (пульсирующий градиент)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Оберни анимации в @media (prefers-reduced-motion: no-preference)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 03 day 6: transitions and animations\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Сборка адаптивного лендинга

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к SaaS Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Финальная сборка лендинга объединяет паттерны недели. position: sticky на шапке удерживает навигацию в viewport при скролле — без JavaScript. Работает, пока родитель не обрезает overflow. aspect-ratio: 16/9 резервирует место под медиа до загрузки — меньше layout shift (CLS), когда картинка «прыгает» и сдвигает текст.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мобильное меню без JS — CSS-only через checkbox hack или :target, но доступность спорна (на неделе 6 заменишь на JS с клавиатурой). Перед сдачей — чеклист: 375px, 768px, 1280px в DevTools; Lighthouse ≥ 85; реальное устройство если есть.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Архитектура CSS: variables → layout → components → utilities. Комментируй breakpoints и grid-решения в файле — через месяц сам забудешь, почему minmax(280px, 1fr).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: sticky + aspect-ratio — два CSS-приёма, которые заменяют килобайты JS.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: position\n- MDN: aspect-ratio

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Собери полноценный лендинг: hero, features (grid), testimonials (flex), CTA, footer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Sticky header с тенью при скролле (CSS position: sticky)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Протестируй на Chrome, Firefox, Edge
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Lighthouse: Performance, Accessibility, Best Practices — все ≥ 85
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Задокументируй breakpoints и grid-решения в комментариях CSS
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь aspect-ratio на hero-изображение или видео-заглушку
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Собери проект в week-03/ — финальная версия SaaS-лендинга
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Лендинг адаптивен 375px–1440px\n- [ ] Использованы и flex, и grid осознанно\n- [ ] Lighthouse ≥ 85 по трём категориям

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Собери полноценный лендинг: hero, features (grid), testimonials (flex), CTA, footer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Sticky header с тенью при скролле (CSS position: sticky)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Протестируй на Chrome, Firefox, Edge
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Lighthouse: Performance, Accessibility, Best Practices — все ≥ 85
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 03 day 7: saas landing final\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Адаптивный лендинг SaaS-продукта (вымышленный) — одностраничник с 5+ секциями.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подробное описание: docs/projects.md — Неделя 3

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Требования:\n- Mobile-first, минимум 2 breakpoint\n- Grid для features и pricing, flex для header/footer/cards\n- CSS-анимации появления секций, prefers-reduced-motion\n- Sticky nav, адаптивная типографика через clamp()

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] Корректный вид на 375px, 768px, 1280px\n- [ ] Нет layout shift при загрузке\n- [ ] Код разделён: variables, layout, components, utilities\n- [ ] Репозиторий с README-screenshot (опционально)\n- [ ] 5+ секций: hero, features, pricing, testimonials, CTA, footer\n- [ ] ≥ 10 осмысленных коммитов за неделю, тег week-03-done\n- [ ] Sticky nav работает при скролле без «прыжков»\n- [ ] Секции появляются с анимацией, но отключаются при prefers-reduced-motion\n- [ ] Pricing и features на CSS Grid, header/footer на Flexbox

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Когда выбираю flex, а когда grid?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что делает repeat(auto-fill, minmax(200px, 1fr))?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как центрировать элемент по обеим осям через flex?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Зачем prefers-reduced-motion и как его применить?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Могу ли я сверстать карточку с кнопкой внизу без фиксированной высоты?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **SaaS Landing** в `learning-log/week-03/`, осмысленная Git-история, тег `week-03-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nАдаптивная вёрстка на Flexbox и Grid\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-03-day-1", "label": "День 1 (Mon): Flexbox — основы"}, {"id": "week-03-day-2", "label": "День 2 (Tue): Flexbox — практические паттерны"}, {"id": "week-03-day-3", "label": "День 3 (Wed): CSS Grid — основы"}, {"id": "week-03-day-4", "label": "День 4 (Thu): Grid — продвинутые макеты"}, {"id": "week-03-day-5", "label": "День 5 (Fri): Адаптивный дизайн"}, {"id": "week-03-day-6", "label": "День 6 (Sat): Переходы и анимации"}, {"id": "week-03-day-7", "label": "День 7 (Sun): Сборка адаптивного лендинга"}, {"id": "week-03-project", "label": "Проект недели"}, {"id": "week-03-review", "label": "Ревью-чеклист"}], "text": "Неделя 3: CSS — Flexbox, Grid, адаптив, анимации Цель недели: научиться строить современные макеты и адаптивные интерфейсы с Flexbox, Grid и анимациями. Литература: Ионетт Дакетт «HTML и CSS» (гл. 12–14), CSS Tricks: Flexbox Guide , CSS Tricks: Grid Guide , web.dev Learn CSS , Every Layout: Sidebar — готовые адаптивные паттерны Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-03/ День 1 (Mon): Flexbox — основы Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к SaaS Landing Теория Flexbox (Flexible Box Layout) решает задачу одномерного выравнивания: элементы в ряд или в колонку. Контейнер с display: flex становится flex-контейнером; прямые д…"} \ No newline at end of file +{"id": "week-03", "title": "CSS layouts", "fullTitle": "Неделя 3: CSS — Flexbox, Grid, адаптив, анимации", "html": "

                                                                                                                                                                                                                        Неделя 3: CSS — Flexbox, Grid, адаптив, анимации

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: научиться строить современные макеты и адаптивные интерфейсы с Flexbox, Grid и анимациями.\nЛитература: Ионетт Дакетт «HTML и CSS» (гл. 12–14), CSS Tricks: Flexbox Guide, CSS Tricks: Grid Guide, web.dev Learn CSS, Every Layout: Sidebar — готовые адаптивные паттерны

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md\nGit: минимум 1 осмысленный коммит каждый день в learning-log/week-03/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Flexbox — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к SaaS Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Flexbox (Flexible Box Layout) решает задачу одномерного выравнивания: элементы в ряд или в колонку. Контейнер с display: flex становится flex-контейнером; прямые дети — flex-элементами. flex-direction задаёт главную ось: row (горизонталь, по умолчанию) или column (вертикаль). justify-content выравнивает по главной оси (space-between, center); align-items — по поперечной. Свойство gap заменяет margin-хаки между элементами — чище и предсказуемее.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        У flex-элементов три рычага размера: flex-grow (как делить свободное место), flex-shrink (как сжиматься) и flex-basis (начальный размер). Сокращение flex: 1 означает flex: 1 1 0% — элемент жадно забирает доступное пространство. По умолчанию align-items: stretch растягивает детей по поперечной оси — карточки в ряду получают одинаковую высоту без фиксированного height.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Flexbox — не замена Grid: он идеален для навигации, тулбаров, центрирования, рядов карточек. Двумерные макеты — задача Grid.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        После двух недель, где элементы просто «текли» друг за другом по умолчанию (block/inline), Flexbox — первый инструмент, который даёт настоящий контроль над расположением. Мысленная модель: представь, что flex-контейнер — это одна полка, а justify-content/align-items — это то, как расставлены предметы вдоль и поперёк этой полки. Главная ось — направление, куда «течёт» полка (row или column), поперечная — перпендикулярное направление.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: до сегодняшнего дня центрирование блока по вертикали требовало хаков (position: absolute + transform, или магические margin); одна строчка display: flex; align-items: center; justify-content: center решает это раз и навсегда, и этот паттерн будет использоваться в каждом следующем проекте маршрута — от карточек товаров до модальных окон с JavaScript.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: шапка сайта с логотипом слева и меню справа раньше делалась через float: left/right с последующим clearfix-хаком для родителя — хрупкая и неочевидная конструкция. С Flexbox это display: flex; justify-content: space-between на родителе — два ребёнка автоматически расходятся по краям без единого float.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение новичков — пытаться решить любую задачу вёрстки Flexbox-ом, включая двумерные сетки (несколько строк и колонок одновременно, которые должны выравниваться друг относительно друга). Flexbox отлично тянет одну ось, но при попытке выстроить сложную сетку карточек с выравниванием и по строкам, и по колонкам одновременно он начинает требовать обходных путей — для этого на этой же неделе есть Grid.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: Flexbox — одна ось, три свойства выравнивания; gap вместо margin между элементами, и сегодняшняя практика с шапкой и рядом карточек — это как раз тот повседневный паттерн, который встретится в 90% проектов впереди.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Flexbox

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сверстай шапку сайта: логотип слева, навигация справа (justify-content: space-between)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Сделай ряд из 3 карточек одинаковой высоты с align-items: stretch
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Центрируй блок по вертикали и горизонтали через flex на родителе
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Поэкспериментируй с flex-wrap при сужении окна
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Используй Flexbox Froggy — пройди 12+ уровней
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь gap вместо margin между карточками — сравни читаемость CSS
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Попробуй flex-direction: column для мобильной шапки
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Шапка не ломается при 768px ширине\n- [ ] Карточки одной высоты без фиксированного height\n- [ ] Flexbox Froggy пройден

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сверстай шапку сайта: логотип слева, навигация справа (justify-content: space-between)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Сделай ряд из 3 карточек одинаковой высоты с align-items: stretch
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Центрируй блок по вертикали и горизонтали через flex на родителе
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Поэкспериментируй с flex-wrap при сужении окна
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 03 day 1: flexbox basics\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Flexbox — практические паттерны

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к SaaS Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        На практике Flexbox решает повторяющиеся паттерны. Sticky footer: body { min-height: 100vh; display: flex; flex-direction: column } и main { flex: 1 } — основной контент растягивается, подвал прижат к низу viewport даже на короткой странице. Кнопка внизу карточки: flex-column на карточке + margin-top: auto на кнопке — она уезжает вниз, текст выше занимает сколько нужно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Разница flex: 1 1 auto и flex: 1 1 0: первый стартует с естественного размера контента, второй — с нуля и делит место поровну. Ловушка: flex-элемент с длинным текстом не сжимается без min-width: 0 — браузер считает минимальный размер по контенту и ломает ряд.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        order и align-self меняют визуальный порядок и выравнивание отдельного элемента — используй редко. order не меняет tab-order для клавиатуры — риск для доступности.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель для сегодняшних паттернов: margin: auto внутри flex-контейнера — это «пружина», которая заполняет всё доступное свободное пространство в указанном направлении, отталкивая элемент к противоположному краю. margin-top: auto толкает элемент вниз, margin-left: auto — вправо. Это не магия, а логичное следствие того, как flexbox распределяет свободное место между элементами.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: карточки товаров, карточки блога, панели с кнопками действий внизу — универсальный паттерн, который повторится в SaaS-лендинге этой недели, а затем в любом React/Vue-компоненте с карточкой. Разобравшись сегодня, что «прижать к низу» — это margin-top: auto, а не фиксированная высота с абсолютным позиционированием, ты решаешь один и тот же класс задач один раз навсегда.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: карточка товара с описанием разной длины — у одного товара одно предложение, у другого — три. Без margin-top: auto на кнопке «Купить», кнопки окажутся на разной высоте в ряду карточек, что выглядит неаккуратно. С этим свойством все кнопки выравниваются по нижнему краю независимо от длины текста выше.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что flex: 1 всегда даёт элементам одинаковую ширину. Если у элементов разный текстовый контент и не задан явный flex-basis: 0, браузер учитывает содержимое при расчёте начального размера — flex: 1 1 auto (значение по умолчанию flex: 1, если задавать по частям, требует внимания) может дать неравные ширины, тогда как flex: 1 1 0% гарантированно делит место поровну независимо от контента.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: margin-top: auto — flex-паттерн «прижать к краю»; min-width: 0 — страховка от переполнения, и оба паттерна сегодня в практике встретятся напрямую в карточке товара и sticky footer.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- CSS Tricks: Flexbox Guide

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Карточка товара: изображение, заголовок, описание, цена, кнопка прижата к низу
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Sticky footer: body как flex-column, main { flex: 1 }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Горизонтальный скролл галереи: flex-wrap: nowrap, overflow-x: auto
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Pagination: ряд кнопок по центру с gap
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг шапки: мобильное меню-иконка (пока без JS — скрытый блок)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь min-width: 0 на карточку с длинным текстом — проверь, что ряд не ломается
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Сверстай card grid на flex с flex-wrap и flex: 1 1 280px
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Кнопка в карточке всегда внизу при разной длине текста\n- [ ] Footer прижат к низу viewport на короткой странице\n- [ ] Галерея скроллится горизонтально на мобильном

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Карточка товара: изображение, заголовок, описание, цена, кнопка прижата к низу
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Sticky footer: body как flex-column, main { flex: 1 }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Горизонтальный скролл галереи: flex-wrap: nowrap, overflow-x: auto
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Pagination: ряд кнопок по центру с gap
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 03 day 2: flexbox patterns\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • flex: 1 на всех детях — не всегда равная ширина, смотри flex-basis
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Забытый min-width: 0 — flex-элемент не сжимается, ломает вёрстку
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Вертикальное центрирование через margin auto вместо flex — устаревший подход
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): CSS Grid — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к SaaS Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CSS Grid — двумерная сетка: строки и колонки одновременно. display: grid на контейнере; grid-template-columns и grid-template-rows задают треки. Единица fr (fraction) делит свободное пространство пропорционально: 1fr 2fr — вторая колонка вдвое шире. repeat(3, 1fr) — три равные колонки; minmax(200px, 1fr) — колонка не уже 200px, но растёт.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Элементы позиционируются через grid-column, grid-row или именованные зоны grid-template-areas. Areas превращают CSS в карту макета: header header / sidebar main / footer footer — читаемо без подсчёта линий. grid-column: span 2 растягивает элемент на две ячейки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Grid vs Flex: grid для страничных макетов, галерей, дашбордов; flex для навигации, рядов кнопок, выравнивания внутри ячейки grid. Часто они работают вместе: grid — скелет страницы, flex — внутри карточки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель: если Flexbox — это одна полка, то Grid — это стеллаж целиком, где ты заранее рисуешь чертёж (сколько полок, какой ширины каждая колонка) и потом расставляешь предметы по конкретным ячейкам этого чертежа. grid-template-areas буквально позволяет нарисовать этот чертёж текстом прямо в CSS — читая код, сразу видно макет страницы, не держа его в голове.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это критично дальше: практически любой реальный сайт — дашборд, интернет-магазин, лендинг — имеет двумерную структуру (шапка на всю ширину, сайдбар и контент рядом, футер снизу), и Grid решает это без единого хака с float или absolute-позиционированием, которые использовались до 2017 года. Это последний крупный layout-инструмент CSS перед тем, как на следующей неделе начнётся JavaScript — Grid и Flex вместе закрывают всю вёрстку, которая понадобится дальше.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: макет «шапка на всю ширину, слева сайдбар 250px, справа контент, снизу футер на всю ширину» через grid-template-areas: \"header header\" \"sidebar main\" \"footer footer\" с grid-template-columns: 250px 1fr — четыре строки CSS вместо десятков строк с float, clear и magic numbers, которые использовались в вёрстке 2010-х годов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что раз Grid двумерный, значит он всегда «лучше» Flexbox и должен использоваться везде. Для одномерных задач (ряд кнопок, центрирование одного блока) Grid избыточен и требует больше кода для того же результата — правило простое: одна ось — Flexbox, две оси одновременно — Grid.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: Grid — две оси и именованные зоны; fr делит пространство, а не проценты от неизвестной ширины, и сегодняшняя практика с areas — тренировка «рисовать» макет прямо в CSS, а не вычислять его на бумаге отдельно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Grid Layout

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сетка 3×2 карточек через grid-template-columns: repeat(3, 1fr)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Макет страницы через areas: header, sidebar, main, footer
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Один элемент растяни на 2 колонки (grid-column: span 2)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Пройди Grid Garden — 12+ уровней
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Сравни тот же макет на flex vs grid — запиши вывод
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь minmax(200px, 1fr) в колонки — проверь поведение при сужении
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Нарисуй схему areas на бумаге, затем перенеси в CSS
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Grid Garden пройден\n- [ ] Макет с areas читаем в CSS без HTML-подсказок\n- [ ] Адаптив: при 600px — одна колонка

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сетка 3×2 карточек через grid-template-columns: repeat(3, 1fr)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Макет страницы через areas: header, sidebar, main, footer
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Один элемент растяни на 2 колонки (grid-column: span 2)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Пройди Grid Garden — 12+ уровней
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 03 day 3: css grid basics\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): Grid — продвинутые макеты

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к SaaS Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Продвинутый Grid убирает необходимость в десятках media queries. repeat(auto-fill, minmax(250px, 1fr)) создаёт responsive-сетку: браузер сам считает, сколько колонок влезет. auto-fill оставляет пустые треки, auto-fit схлопывает их — на широком экране карточки растягиваются, а не остаётся пустая колонка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Grid stacking — два элемента в одной ячейке: наложи текст на изображение, задав обоим grid-row: 1; grid-column: 1. Subgrid (где поддерживается) выравнивает вложенные сетки с родительской — карточки в ряду получают согласованные строки заголовков.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Правило выбора: 1D → flex, 2D → grid. Навигация и кнопки — flex; pricing table, features grid, dashboard — grid. Вложенный grid внутри main — sidebar фиксированной ширины, контент на 1fr.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель: auto-fill/auto-fit с minmax() — это не набор фиксированных breakpoint'ов «на 3 колонки при 1024px», а формула, которая пересчитывается на каждый пиксель ширины экрана. Вместо того чтобы перечислять устройства (телефон, планшет, десктоп), ты описываешь правило «сколько минимум места нужно карточке» — и браузер сам решает, сколько карточек влезет в ряд на любом экране, включая устройства, которые ещё не существуют.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: на завтрашнем дне про адаптивный дизайн ты будешь совмещать этот подход с явными breakpoints через @media — но там, где формула auto-fill/minmax() покрывает задачу, лишний media query не нужен. Это экономит десятки строк CSS в каждом следующем проекте и делает интерфейс устойчивым к нестандартным размерам экрана без дополнительных правок.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: галерея из 7 карточек с grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)) покажет 5 колонок на экране 1200px и автоматически перестроится в 2 колонки на 500px — без единой строчки @media, просто потому что при 500px помещается только 2 колонки по 200px+.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — путать auto-fill и auto-fit, думая что они одинаковы. Разница проявляется только когда элементов меньше, чем может поместиться колонок: auto-fill сохранит пустые невидимые треки (карточки останутся у левого края, не растягиваясь), а auto-fit схлопнет пустые треки и растянет существующие карточки на всю доступную ширину.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: auto-fill/auto-fit + minmax() — адаптивная сетка без ручных breakpoints, и разница между ними стоит того, чтобы проверить её сегодня на практике вживую, а не запоминать теоретически.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- CSS Tricks: Grid Guide

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Галерея с grid-template-columns: repeat(auto-fill, minmax(200px, 1fr))
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Dashboard: sidebar 250px, main 1fr, виджеты внутри main — вложенный grid
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Карточка с overlay-текстом поверх изображения (grid stack)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Pinterest-подобная сетка разной высоты (разный grid-row: span N)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг блога недели 2 на grid-layout
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сравни auto-fill и auto-fit на одной сетке — зафиксируй разницу скриншотом
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь subgrid (если браузер поддерживает) или запиши fallback
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Галерея адаптируется без единой media query\n- [ ] Dashboard читаем на 1024px и 375px\n- [ ] Осознанный выбор flex vs grid в каждом блоке

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Галерея с grid-template-columns: repeat(auto-fill, minmax(200px, 1fr))
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Dashboard: sidebar 250px, main 1fr, виджеты внутри main — вложенный grid
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Карточка с overlay-текстом поверх изображения (grid stack)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Pinterest-подобная сетка разной высоты (разный grid-row: span N)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 03 day 4: advanced grid layouts\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Адаптивный дизайн

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к SaaS Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Адаптивный дизайн — не «версия для мобильного», а один интерфейс, плавно подстраивающийся под экран. Подход mobile-first: базовые стили пишутся для узкого экрана (375px), затем @media (min-width: 768px) добавляют возможности для планшета и десктопа. Расширять проще, чем «отрезать» лишнее с десктопной версии.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Breakpoints (480, 768, 1024, 1280px) — не догма, а ориентиры. Breakpoint выбирай там, где ломается контент: навигация не влезает, карточки сжимаются нечитаемо. meta viewport в <head> обязателен: без него мобильный браузер покажет «уменьшенный десктоп».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Относительные единицы (rem, %, vw) и max-width: 100% на изображениях предотвращают горизонтальный скролл. Touch targets на мобильном — минимум 44×44px: пальцу нужна площадь больше, чем точке курсора. Container queries (@container) — следующий уровень: стили от размера контейнера, а не viewport.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель mobile-first: представь, что пишешь стили для самого маленького и ограниченного устройства, а затем — по мере роста экрана — добавляешь возможности, как открываешь дополнительные комнаты в доме по мере роста семьи. Desktop-first работает наоборот: сначала строишь весь особняк, а потом судорожно «сносишь стены» media queries, пытаясь втиснуть его в маленькую квартиру — отсюда и происходит большинство «сломанных на мобильном» сайтов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: с недели 4+ появится реальный трафик с мобильных устройств (в среднем более половины посетителей любого сайта), а на собеседованиях адаптивность — один из первых вопросов о практическом опыте. Привычка мыслить mobile-first, заложенная сегодня, экономит часы переделок в каждом будущем проекте, где по умолчанию тянет верстать «как на своём большом мониторе».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: карточка с фиксированной шириной width: 400px и padding: 40px, написанная сначала для десктопа, на экране 375px вызовет горизонтальный скролл всей страницы — придётся добавлять media query, чтобы «исправить» то, что изначально не работало. Если же сначала написать width: 100%; padding: 1rem, а на широких экранах через @media (min-width: 768px) добавить max-width: 400px, скролла не возникнет никогда.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — выбирать breakpoints по размерам конкретных моделей телефонов («iPhone — 390px, значит ставим breakpoint на 390»). Экранов существуют тысячи размеров, и привязка к конкретным устройствам устаревает с каждым новым релизом телефонов. Правильный ориентир — не устройство, а момент, когда реальный контент (текст, навигация, карточки) перестаёт помещаться корректно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: mobile-first + breakpoint по поломке контента, не по модели телефона — и сегодняшняя практика с перепиской стилей от 375px вверх — это тренировка именно такого мышления.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Responsive design

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши стили mobile-first: база 375px, затем 768px, 1024px
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Навигация: горизонтальная на десктопе, вертикальный список на мобильном
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Типографика: уменьши font-size и spacing на мобильном
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Таблица: горизонтальный скролл или card-view на узком экране
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь в DevTools Device Mode минимум 4 размера
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь meta viewport если отсутствует — проверь масштабирование
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Увеличь padding кнопок на мобильном до touch-friendly размеров
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Нет горизонтального скролла на 375px\n- [ ] Touch targets ≥ 44×44px на мобильном\n- [ ] Breakpoints логичны, не «магические» без причины

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши стили mobile-first: база 375px, затем 768px, 1024px
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Навигация: горизонтальная на десктопе, вертикальный список на мобильном
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Типографика: уменьши font-size и spacing на мобильном
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Таблица: горизонтальный скролл или card-view на узком экране
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 03 day 5: responsive mobile-first\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Переходы и анимации

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к SaaS Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CSS-переходы (transition) анимируют изменение свойства от значения A к B: transition: transform 0.2s ease. Указываешь свойство, длительность, функцию времени (ease, ease-in-out, cubic-bezier). Для hover-эффектов и смены состояний — идеальный инструмент.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        @keyframes + animation — для многошаговых анимаций: появление модалки, пульсация skeleton loader, бесконечный спиннер. Переход срабатывает при смене класса; keyframes идут по расписанию независимо.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Производительность: анимируй только transform и opacity — они обрабатываются на GPU и не вызывают reflow всей страницы. Анимация width, height, margin — дорого. Длительность UI-переходов: 150–300ms; дольше кажется тормозным. Обязательно учитывай prefers-reduced-motion: reduce — у пользователей с вестибулярными нарушениями анимации могут вызывать тошноту.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель: transition — это ответ на вопрос «как измениться из точки А в точку Б», а @keyframes — это заранее срежиссированный мини-фильм с несколькими сценами, который проигрывается независимо от того, менял ли пользователь состояние элемента. Hover на кнопке — это A → Б, поэтому transition; бесконечно пульсирующий skeleton loader не имеет «состояния Б», к которому он стремится — поэтому keyframes.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: анимации — то, что отличает статичный сайт от «живого» продукта, и на неделе 6 с JavaScript ты будешь программно добавлять/убирать классы, запускающие эти же CSS-переходы (например, класс .open на модалке) — сегодняшнее понимание, что именно class toggling запускает transition, напрямую подготавливает к событийной модели JS.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: карточка с transition: transform 0.2s ease и :hover { transform: translateY(-4px) } создаёт лёгкий эффект «приподнимания» без единой строчки JavaScript — GPU обрабатывает transform без пересчёта всей раскладки страницы, поэтому анимация остаётся плавной даже на слабых устройствах.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — анимировать width или top/left для перемещения и изменения размера элементов, потому что это «интуитивно понятнее». На деле такие анимации заставляют браузер пересчитывать позиции всех соседних элементов на каждом кадре (reflow) — на сложной странице это заметно проседает по FPS, особенно на мобильных. transform: translate() и transform: scale() визуально дают тот же результат, но обрабатываются на отдельном GPU-слое без reflow.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: transition для состояний, @keyframes для сцен; только transform и opacity на проде — и это правило особенно важно проверить в сегодняшней практике на skeleton loader, где неправильный выбор свойства для анимации сразу заметен по «дёрганности».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: CSS transitions\n- MDN: CSS animations

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Плавные hover-эффекты на кнопках и карточках (transition: 0.2s ease)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Анимация появления модального блока через @keyframes fadeIn
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Skeleton loader для карточки (пульсирующий градиент)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Оберни анимации в @media (prefers-reduced-motion: no-preference)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Избегай анимации width/height — используй transform и opacity
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь will-change: transform на анимируемый элемент (осторожно, не везде)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Сравни ease, ease-in-out, cubic-bezier — выбери для кнопок
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Анимации на GPU-свойствах (transform, opacity)\n- [ ] prefers-reduced-motion учтён\n- [ ] Переходы не медленнее 300ms для UI-интеракций

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Плавные hover-эффекты на кнопках и карточках (transition: 0.2s ease)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Анимация появления модального блока через @keyframes fadeIn
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Skeleton loader для карточки (пульсирующий градиент)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Оберни анимации в @media (prefers-reduced-motion: no-preference)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 03 day 6: transitions and animations\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Сборка адаптивного лендинга

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к SaaS Landing

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Финальная сборка лендинга объединяет паттерны недели. position: sticky на шапке удерживает навигацию в viewport при скролле — без JavaScript. Работает, пока родитель не обрезает overflow. aspect-ratio: 16/9 резервирует место под медиа до загрузки — меньше layout shift (CLS), когда картинка «прыгает» и сдвигает текст.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мобильное меню без JS — CSS-only через checkbox hack или :target, но доступность спорна (на неделе 6 заменишь на JS с клавиатурой). Перед сдачей — чеклист: 375px, 768px, 1280px в DevTools; Lighthouse ≥ 85; реальное устройство если есть.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Архитектура CSS: variables → layout → components → utilities. Комментируй breakpoints и grid-решения в файле — через месяц сам забудешь, почему minmax(280px, 1fr).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Сегодняшний день — не про новую теорию, а про сборку всего изученного за неделю в единый рабочий продукт, и именно это упражнение показывает, насколько прочно улеглись Flexbox, Grid, адаптив и анимации. Мысленная модель финальной сборки: variables → layout → components → utilities — это порядок, в котором строят дом: сначала фундамент и коммуникации (токены), потом несущие стены (layout на grid/flex), потом мебель и отделка (компоненты), и только в конце — мелкие штрихи вроде отдельного класса .text-center (utilities).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: с недели 4 весь HTML/CSS фундамент считается «данностью» — фокус сместится на JavaScript, который будет управлять уже готовой вёрсткой (переключать классы, добавлять контент, обрабатывать формы). Если сегодня лендинг не собран целостно, а состоит из разрозненных экспериментов по дням, будущая работа с ним через JS будет затруднена — нельзя надёжно навешивать обработчики на структуру, которая ещё не устоялась.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: position: sticky на шапке с top: 0 работает отлично, пока где-то выше по дереву DOM у родителя не стоит overflow: hidden или overflow: auto — в этом случае sticky «ломается» без явной ошибки в консоли, и разработчики тратят часы, не понимая, почему шапка вдруг перестала прилипать. Это одна из самых частых практических ловушек sticky-позиционирования.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать, что раз лендинг «выглядит нормально» на своём мониторе, значит адаптивность готова. Реальная проверка требует явного прогона через DevTools Device Mode на нескольких размерах и, желательно, хотя бы одного реального устройства — многие баги (например, 100vh на мобильных браузерах с адресной строкой) проявляются только в реальных условиях, а не в эмуляции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: sticky + aspect-ratio — два CSS-приёма, которые заменяют килобайты JS, а сегодняшняя итоговая сборка — экзамен на то, что весь материал недели работает вместе, а не по отдельности в изолированных примерах.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: position\n- MDN: aspect-ratio

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Собери полноценный лендинг: hero, features (grid), testimonials (flex), CTA, footer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Sticky header с тенью при скролле (CSS position: sticky)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Протестируй на Chrome, Firefox, Edge
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Lighthouse: Performance, Accessibility, Best Practices — все ≥ 85
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Задокументируй breakpoints и grid-решения в комментариях CSS
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь aspect-ratio на hero-изображение или видео-заглушку
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Собери проект в week-03/ — финальная версия SaaS-лендинга
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Лендинг адаптивен 375px–1440px\n- [ ] Использованы и flex, и grid осознанно\n- [ ] Lighthouse ≥ 85 по трём категориям

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Собери полноценный лендинг: hero, features (grid), testimonials (flex), CTA, footer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Sticky header с тенью при скролле (CSS position: sticky)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Протестируй на Chrome, Firefox, Edge
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Lighthouse: Performance, Accessibility, Best Practices — все ≥ 85
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 03 day 7: saas landing final\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Адаптивный лендинг SaaS-продукта (вымышленный) — одностраничник с 5+ секциями.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подробное описание: docs/projects.md — Неделя 3

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Требования:\n- Mobile-first, минимум 2 breakpoint\n- Grid для features и pricing, flex для header/footer/cards\n- CSS-анимации появления секций, prefers-reduced-motion\n- Sticky nav, адаптивная типографика через clamp()

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] Корректный вид на 375px, 768px, 1280px\n- [ ] Нет layout shift при загрузке\n- [ ] Код разделён: variables, layout, components, utilities\n- [ ] Репозиторий с README-screenshot (опционально)\n- [ ] 5+ секций: hero, features, pricing, testimonials, CTA, footer\n- [ ] ≥ 10 осмысленных коммитов за неделю, тег week-03-done\n- [ ] Sticky nav работает при скролле без «прыжков»\n- [ ] Секции появляются с анимацией, но отключаются при prefers-reduced-motion\n- [ ] Pricing и features на CSS Grid, header/footer на Flexbox

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Когда выбираю flex, а когда grid?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что делает repeat(auto-fill, minmax(200px, 1fr))?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как центрировать элемент по обеим осям через flex?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Зачем prefers-reduced-motion и как его применить?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Могу ли я сверстать карточку с кнопкой внизу без фиксированной высоты?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **SaaS Landing** в `learning-log/week-03/`, осмысленная Git-история, тег `week-03-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nАдаптивная вёрстка на Flexbox и Grid\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-03-day-1", "label": "День 1 (Mon): Flexbox — основы"}, {"id": "week-03-day-2", "label": "День 2 (Tue): Flexbox — практические паттерны"}, {"id": "week-03-day-3", "label": "День 3 (Wed): CSS Grid — основы"}, {"id": "week-03-day-4", "label": "День 4 (Thu): Grid — продвинутые макеты"}, {"id": "week-03-day-5", "label": "День 5 (Fri): Адаптивный дизайн"}, {"id": "week-03-day-6", "label": "День 6 (Sat): Переходы и анимации"}, {"id": "week-03-day-7", "label": "День 7 (Sun): Сборка адаптивного лендинга"}, {"id": "week-03-project", "label": "Проект недели"}, {"id": "week-03-review", "label": "Ревью-чеклист"}], "text": "Неделя 3: CSS — Flexbox, Grid, адаптив, анимации Цель недели: научиться строить современные макеты и адаптивные интерфейсы с Flexbox, Grid и анимациями. Литература: Ионетт Дакетт «HTML и CSS» (гл. 12–14), CSS Tricks: Flexbox Guide , CSS Tricks: Grid Guide , web.dev Learn CSS , Every Layout: Sidebar — готовые адаптивные паттерны Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-03/ День 1 (Mon): Flexbox — основы Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к SaaS Landing Теория Flexbox (Flexible Box Layout) решает задачу одномерного выравнивания: элементы в ряд или в колонку. Контейнер с display: flex становится flex-контейнером; прямые д…"} \ No newline at end of file diff --git a/docs/weeks/04.json b/docs/weeks/04.json index 6a21498..b193bc1 100644 --- a/docs/weeks/04.json +++ b/docs/weeks/04.json @@ -1 +1 @@ -{"id": "week-04", "title": "Git advanced", "fullTitle": "Неделя 4: Git Advanced, GitHub workflow, DevTools", "html": "

                                                                                                                                                                                                                        Неделя 4: Git Advanced, GitHub workflow, DevTools

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: углубить Git (ветки, merge, rebase, PR), оформить learning-log как OSS-проект, освоить DevTools.\nПредусловие: Git с недели 1 — репозиторий learning-log уже существует, ежедневные коммиты — привычка.\nЛитература: Scott Chacon, Ben Straub «Pro Git» (git-scm.com/book), GitHub Docs, Chrome DevTools Docs, Conventional Commits, Oh Shit, Git!?! — экстренные сценарии

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md\nGit: минимум 1 осмысленный коммит каждый день в learning-log/week-04/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Git — ревизия основ + git log как инструмент

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к OSS Workflow Kit

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Перед углублением в ветки стоит закрепить фундамент: Git отслеживает три состояния каждого файла — изменён (modified), проиндексирован (staged), зафиксирован (committed). Каждый коммит получает уникальный SHA-хеш — «отпечаток» снимка. git log --oneline --graph --all показывает историю как дерево решений, а не список сохранений.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        git show <hash> раскрывает конкретный коммит: автор, дата, diff. git diff — разница между working directory и staging; git diff --staged — что войдёт в следующий коммит. Это инструменты расследования: «что я наменял и зачем?».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Conventional Commits — соглашение об именовании: feat:, fix:, docs:, chore:. Префикс сразу говорит тип изменения; в будущем из таких сообщений автогенерируется CHANGELOG. Хорошее сообщение отвечает на вопрос «зачем», а не «что нажал».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: git log — дневник решений; осмысленные сообщения коммитов = документация для будущего себя.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Pro Git: Основы — три состояния, SHA коммитов\n- Conventional Commits

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. В learning-log выполни git log --oneline -15 — опиши в week-04/REFLECTION.md паттерн своих сообщений
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Исправь 2 слабых commit message через git rebase -i HEAD~3 только если ещё не пушил; иначе — лучше не переписывать историю
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь в корень learning-log расширенный .gitignore (OS, IDE, env, build)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Разбей незакоммиченные правки week-03 на 2 атомарных коммита через staging
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. git blame week-03/index.html — кто и когда менял строку (это ты — привыкай к прослеживаемости)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Репозиторий инициализирован, секреты не в git\n- [ ] Минимум 3 коммита с понятными сообщениями\n- [ ] git status чист после коммита

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. В learning-log выполни git log --oneline -15 — опиши в week-04/REFLECTION.md паттерн своих сообщений
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Исправь 2 слабых commit message через git rebase -i HEAD~3 только если ещё не пушил; иначе — лучше не переписывать историю
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь в корень learning-log расширенный .gitignore (OS, IDE, env, build)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 04 day 1: git init and first commits\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Ветки, слияние и конфликты

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к OSS Workflow Kit

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ветка в Git — просто указатель на коммит. Создать ветку дёшево: git switch -c feature/header ответвляет от текущего состояния, и ты работаешь изолированно, не ломая main. Когда фича готова — слияние (merge) переносит изменения обратно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Fast-forward merge возможен, если main не получил новых коммитов с момента ответвления: указатель main просто «перепрыгнет» на конец feature-ветки. Иначе Git создаёт merge commit — коммит с двумя родителями. git merge --no-ff принудительно создаёт merge commit даже при возможности ff — сохраняет видимость ветки в истории.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конфликт возникает, когда одна и та же строка изменена в обеих ветках. Git вставляет маркеры <<<<<<<, =======, >>>>>>> — ты вручную выбираешь итог, git add, git commit. Конфликт — не катастрофа, а диалог между версиями. git stash временно прячет незакоммиченные правки, если нужно срочно переключить ветку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: ветка — дешёвый черновик; merge — слияние черновика с основной линией.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Pro Git: Ветвление

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай ветку feature/dark-theme, добавь тёмную тему
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Вернись на main, измени тот же файл — спровоцируй конфликт
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Смержи ветку, разреши конфликт вручную
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Попрактикуй git stash при переключении веток с незакоммиченными правками
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Нарисуй схему веток после всех операций
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сравни git merge --no-ff и fast-forward — посмотри историю
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. После разрешения конфликта проверь, что сайт работает
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Конфликт разрешён осознанно, не удалён «всё чужое»\n- [ ] История показывает merge (или осознанный ff)\n- [ ] Понимаю разницу между branch и commit

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай ветку feature/dark-theme, добавь тёмную тему
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Вернись на main, измени тот же файл — спровоцируй конфликт
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Смержи ветку, разреши конфликт вручную
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Попрактикуй git stash при переключении веток с незакоммиченными правками
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 04 day 2: branches merge conflicts\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Коммит в detached HEAD — изменения не на ветке
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • git add . без проверки — случайно добавил .env
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Разрешение конфликта без тестирования — сломанный код в main
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): GitHub и удалённый workflow

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к OSS Workflow Kit

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Локальный Git — половина workflow. Remote (обычно origin на GitHub) — копия репозитория на сервере. git push публикует коммиты; git pull забирает чужие и сливает с твоими. Флаг -u при первом push связывает локальную ветку с удалённой — дальше достаточно git push.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Pull Request — запрос на слияние ветки с описанием изменений. Даже в solo-проекте PR учит дисциплине review: ты смотришь diff глазами «чужого» разработчика до merge. Стратегии merge на GitHub: обычный merge, squash (все коммиты ветки → один), rebase. Squash даёт чистую линейную историю main.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Issues — трекер задач: баг, улучшение, идея. Коммит с fix #12 в сообщении автоматически закрывает issue №12. Fork + upstream — паттерн open source: форкаешь чужой репозиторий, вносишь правки, открываешь PR в оригинал.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: GitHub = remote + социальный слой; PR — разговор о коде до попадания в main.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- GitHub: Hello World

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай репозиторий на GitHub (public), подключи remote
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Запушь main, создай ветку feature/readme, добавь README.md
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Открой Pull Request с описанием изменений
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Смержи PR через GitHub UI (Squash or Merge — изучи разницу)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Создай Issue с багом или улучшением, закрой через коммит fix: ...
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Клонируй репозиторий в другую папку — убедись, что clone работает
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь в README badges (build, license) — заготовка под неделю
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Код на GitHub, локальный и remote синхронизированы\n- [ ] Минимум 1 PR с описанием\n- [ ] README содержит название, описание, как запустить

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай репозиторий на GitHub (public), подключи remote
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Запушь main, создай ветку feature/readme, добавь README.md
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Открой Pull Request с описанием изменений
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Смержи PR через GitHub UI (Squash or Merge — изучи разницу)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 04 day 3: github remote and PR\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): DevTools — Elements и Console

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к OSS Workflow Kit

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Chrome DevTools — рентген твоей страницы. Панель Elements показывает живое DOM-дерево: кликни на узел — увидишь применённые стили, box model, flex/grid overlay. Вкладка Styles перечисляет все CSS-правила с указанием файла и строки; перечёркнутое свойство проиграло в каскаде — ищи победителя выше. Computed — итоговые вычисленные значения после каскада, наследования и браузерных дефолтов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Live-редактирование CSS в DevTools — быстрый эксперимент: подобрал отступ — перенеси в файл. Flex/Grid overlay рисует треки и gap поверх страницы — не гадай, смотри. В Console $0 — ссылка на элемент, выбранный в Elements; мост между визуальным и программным исследованием.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        console.log — базовый вывод; console.table — таблица для массивов объектов; console.group — группировка связанных логов. Уровни warn и error выделяются визуально и фильтруются.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: Styles — «кто перебил?», Computed — «что в итоге?»; overlay — «как устроена сетка?».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Chrome DevTools: Overview

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Открой лендинг, исследуй box model каждой секции в Elements
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Включи flex/grid overlay для layout-контейнеров
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Найди и исправь «лишний» margin через live edit, перенеси в CSS-файл
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. В Console: выбери элемент, измени текст через $0.textContent
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Добавь console.log в будущий JS-файл (заготовка) — проверь вывод
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Используй console.table для массива объектов (заготовка данных)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Найди перечёркнутое свойство в Styles — объясни, почему оно не применилось
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Умею найти источник стиля в панели Styles (файл и строка)\n- [ ] Использовал flex/grid overlay\n- [ ] Знаю разницу Computed vs Styles

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Открой лендинг, исследуй box model каждой секции в Elements
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Включи flex/grid overlay для layout-контейнеров
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Найди и исправь «лишний» margin через live edit, перенеси в CSS-файл
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. В Console: выбери элемент, измени текст через $0.textContent
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 04 day 4: devtools elements console\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): DevTools — Network, Sources, Performance

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к OSS Workflow Kit

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Панель Network показывает каждый HTTP-запрос при загрузке страницы: URL, статус, размер, время. Waterfall — диаграмма «кто за кем»: видно, что блокирует рендер (тяжёлые картинки, синхронные скрипты). Статусы: 200 OK, 304 Not Modified (из кэша), 404 Not Found. При разработке включай Disable cache, иначе видишь устаревшие файлы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Sources — отладка JavaScript: breakpoint останавливает выполнение в точке; step over/into проходят по строкам; watch expressions следят за переменными. Performance записывает профиль: FPS, long tasks, jank при скролле. Lighthouse в DevTools — аудит Performance, Accessibility, Best Practices с конкретными рекомендациями.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Вкладка Application — хранилища браузера: Local Storage, Cookies, Service Workers (обзор на будущее). Тяжёлый ресурс в Network — первый кандидат на оптимизацию: сжатие, WebP, lazy loading.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: Network waterfall — карта загрузки; Lighthouse — чеклист перед сдачей.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Chrome DevTools: Network\n- Chrome DevTools: Performance

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перезагрузи страницу с Network open — проанализируй waterfall
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Найди самый тяжёлый ресурс, оптимизируй (сжатие изображения)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Запусти Lighthouse, сохрани отчёт, исправь 2+ замечания
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. В Sources поставь breakpoint (на inline script или будущий JS)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Запиши Performance profile при скролле — есть ли jank?
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Отфильтруй Network по CSS/JS — оцени общий вес страницы
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь Application → Local Storage (пока пусто — заготовка под неделю 7)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Понимаю статусы 200, 304, 404 в Network\n- [ ] Lighthouse score улучшен после правок\n- [ ] Умею ставить breakpoint и читать call stack

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перезагрузи страницу с Network open — проанализируй waterfall
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Найди самый тяжёлый ресурс, оптимизируй (сжатие изображения)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Запусти Lighthouse, сохрани отчёт, исправь 2+ замечания
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. В Sources поставь breakpoint (на inline script или будущий JS)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 04 day 5: devtools network performance\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Workflow разработчика

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к OSS Workflow Kit

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Workflow — это привычки, которые масштабируются от solo до команды. GitHub Flow — простейший: main всегда deployable, каждая фича в ветке → PR → merge. Git Flow сложнее (develop, release) — избыточен для учебных проектов. Trunk-Based — короткоживущие ветки, частые merge в main — для зрелых команд с CI.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Conventional Commits (feat:, fix:, docs:) — единый язык сообщений; из них генерируется CHANGELOG. Pre-commit checklist: git diff глазами ревьюера, нет ли .env в staging, страница открывается, Lighthouse не упал. Prettier убирает споры о форматировании — один .prettierrc на проект.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        VS Code Git panel, diff view, GitLens — ускоряют ежедневную работу. Code review — не придирка, а передача знаний: даже self-review перед push ловит опечатки и лишние файлы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: GitHub Flow + Conventional Commits + self-review = профессиональный минимум.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Conventional Commits\n- GitHub Flow

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Переименуй последние коммиты сообщениями в стиле Conventional Commits (если нужно — git rebase осторожно или новые коммиты)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Настрой Prettier в VS Code, отформатируй CSS/HTML
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай PR template в .github/pull_request_template.md
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проведи self-review: открой diff последнего PR глазами ревьюера
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Составь личный чеклист перед каждым push (5 пунктов)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь .prettierrc с базовыми настройками (semi, singleQuote)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Напиши CHANGELOG.md с секцией для недель 1–4
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Коммиты следуют единому стилю сообщений\n- [ ] Prettier настроен и применён\n- [ ] Есть PR template или чеклист в заметках

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Переименуй последние коммиты сообщениями в стиле Conventional Commits (если нужно — git rebase осторожно или новые коммиты)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Настрой Prettier в VS Code, отформатируй CSS/HTML
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай PR template в .github/pull_request_template.md
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проведи self-review: открой diff последнего PR глазами ревьюера
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 04 day 6: conventional commits prettier\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Интеграция и практика

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к OSS Workflow Kit

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Инструменты расследования истории: git log — хронология; git diff — разница между состояниями; git show — один коммит целиком; git blame — кто и когда изменил каждую строку файла. Blame не для поиска виноватых, а для понимания контекста: «зачем эта строка появилась?».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Отмена изменений — два разных инструмента. git revert <hash> создаёт новый коммит, отменяющий старый — безопасно для shared main, история не переписывается. git reset --hard откатывает указатель ветки — переписывает историю; только на локальных ветках, никогда на запушенном main без согласования.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        GitHub Pages публикует статику из ветки gh-pages или через Actions — бесплатный live demo для портфолио. git clone в новую папку — тест: «смогу ли я развернуть проект с нуля?» — must-have перед сдачей.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: revert — безопасная отмена; reset --hard — только локально; clone — финальный тест переносимости.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Pro Git: Отмена изменений\n- GitHub Pages

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Клонируй свой репозиторий в новую папку — проверь, что всё работает
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Найди автора строки через git blame для одного CSS-файла
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Задеплой лендинг на GitHub Pages (branch gh-pages или Actions)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь live URL в DevTools Network и Lighthouse
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Напиши CONTRIBUTING.md с правилами коммитов и веток
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь LICENSE (MIT) и обнови README со скриншотами недель 1–3
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Поставь тег week-04-done на финальный коммит
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Сайт доступен по публичному URL\n- [ ] Clone → open работает без ручных правок\n- [ ] CONTRIBUTING.md или раздел в README описывает workflow

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Клонируй свой репозиторий в новую папку — проверь, что всё работает
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Найди автора строки через git blame для одного CSS-файла
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Задеплой лендинг на GitHub Pages (branch gh-pages или Actions)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь live URL в DevTools Network и Lighthouse
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 04 day 7: github pages contributing\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Open-source мини-проект — публичный репозиторий с лендингом, полным Git-историей и деплоем.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подробное описание: docs/projects.md — Неделя 4

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Требования:\n- Минимум 10 коммитов, 2+ ветки, 1 merged PR\n- README, .gitignore, LICENSE (MIT)\n- GitHub Pages или аналог — live demo\n- CONTRIBUTING.md с Conventional Commits

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] История коммитов читаема и атомарна\n- [ ] PR с описанием и self-review\n- [ ] Live demo работает\n- [ ] Нет секретов и лишних файлов в репозитории\n- [ ] README с badges, скриншотами проектов недель 1–3\n- [ ] ≥ 2 feature-ветки, осознанный выбор merge vs rebase\n- [ ] CHANGELOG.md с записями по Conventional Commits\n- [ ] GitHub Pages деплоит week-03 лендинг по публичному URL\n- [ ] Тег week-04-done на финальном коммите

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • В чём разница git add, git commit, git push?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как отменить последний коммит, не потеряв изменения?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что показывает git log --oneline --graph?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как найти, какой CSS-файл задаёт конкретное свойство в DevTools?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Могу ли я объяснить flow: branch → commit → push → PR → merge?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **OSS Workflow Kit** в `learning-log/week-04/`, осмысленная Git-история, тег `week-04-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nПрофессиональный Git-workflow и DevTools\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-04-day-1", "label": "День 1 (Mon): Git — ревизия основ + git log как инструмент"}, {"id": "week-04-day-2", "label": "День 2 (Tue): Ветки, слияние и конфликты"}, {"id": "week-04-day-3", "label": "День 3 (Wed): GitHub и удалённый workflow"}, {"id": "week-04-day-4", "label": "День 4 (Thu): DevTools — Elements и Console"}, {"id": "week-04-day-5", "label": "День 5 (Fri): DevTools — Network, Sources, Performance"}, {"id": "week-04-day-6", "label": "День 6 (Sat): Workflow разработчика"}, {"id": "week-04-day-7", "label": "День 7 (Sun): Интеграция и практика"}, {"id": "week-04-project", "label": "Проект недели"}, {"id": "week-04-review", "label": "Ревью-чеклист"}], "text": "Неделя 4: Git Advanced, GitHub workflow, DevTools Цель недели: углубить Git (ветки, merge, rebase, PR), оформить learning-log как OSS-проект, освоить DevTools. Предусловие: Git с недели 1 — репозиторий learning-log уже существует, ежедневные коммиты — привычка. Литература: Scott Chacon, Ben Straub «Pro Git» ( git-scm.com/book ), GitHub Docs , Chrome DevTools Docs , Conventional Commits , Oh Shit, Git!?! — экстренные сценарии Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-04/ День 1 (Mon): Git — ревизия основ + git log как инструмент Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к OSS Workflow Kit Теория Перед углублением в ветки стоит…"} \ No newline at end of file +{"id": "week-04", "title": "Git advanced", "fullTitle": "Неделя 4: Git Advanced, GitHub workflow, DevTools", "html": "

                                                                                                                                                                                                                        Неделя 4: Git Advanced, GitHub workflow, DevTools

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: углубить Git (ветки, merge, rebase, PR), оформить learning-log как OSS-проект, освоить DevTools.\nПредусловие: Git с недели 1 — репозиторий learning-log уже существует, ежедневные коммиты — привычка.\nЛитература: Scott Chacon, Ben Straub «Pro Git» (git-scm.com/book), GitHub Docs, Chrome DevTools Docs, Conventional Commits, Oh Shit, Git!?! — экстренные сценарии

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md\nGit: минимум 1 осмысленный коммит каждый день в learning-log/week-04/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Git — ревизия основ + git log как инструмент

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к OSS Workflow Kit

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Перед углублением в ветки стоит закрепить фундамент: Git отслеживает три состояния каждого файла — изменён (modified), проиндексирован (staged), зафиксирован (committed). Каждый коммит получает уникальный SHA-хеш — «отпечаток» снимка. git log --oneline --graph --all показывает историю как дерево решений, а не список сохранений.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        git show <hash> раскрывает конкретный коммит: автор, дата, diff. git diff — разница между working directory и staging; git diff --staged — что войдёт в следующий коммит. Это инструменты расследования: «что я наменял и зачем?».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Conventional Commits — соглашение об именовании: feat:, fix:, docs:, chore:. Префикс сразу говорит тип изменения; в будущем из таких сообщений автогенерируется CHANGELOG. Хорошее сообщение отвечает на вопрос «зачем», а не «что нажал».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: думай о Git не как о резервном копировании, а как о фотоальбоме проекта. Каждый коммит — цельный снимок всех файлов в конкретный момент, а не список построчных правок (в этом отличие от систем контроля версий старого поколения). Staging area — «поднос», на который ты выкладываешь изменения перед тем, как вклеить их в альбом одним кадром: можно взять не все файлы, а только логически связанные.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: уже завтра git diff и git log понадобятся при разборе конфликтов слияния, а через несколько недель, когда придётся разбираться в чужом (или своём трёхмесячной давности) коде, именно история коммитов станет главным источником контекста — не документация, а сам git log объяснит, почему код выглядит именно так.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: после трёх дней работы git log --oneline может выглядеть так: a1b2c3d feat: add hero section, e4f5g6h fix: broken flex layout on mobile, i7j8k9l docs: update README. По одному этому списку — без взгляда на код — понятно, что происходило в проекте.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички думают, что git add уже «сохраняет» файл. На самом деле фиксирует изменения только git commit; add лишь готовит их к следующему снимку, и их легко убрать из staging через git restore --staged до коммита. Сегодняшняя практика с git log, git blame и разбором commit message опирается именно на понимание этих трёх состояний.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: git log — дневник решений; осмысленные сообщения коммитов = документация для будущего себя.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Pro Git: Основы — три состояния, SHA коммитов\n- Conventional Commits

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. В learning-log выполни git log --oneline -15 — опиши в week-04/REFLECTION.md паттерн своих сообщений
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Исправь 2 слабых commit message через git rebase -i HEAD~3 только если ещё не пушил; иначе — лучше не переписывать историю
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь в корень learning-log расширенный .gitignore (OS, IDE, env, build)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Разбей незакоммиченные правки week-03 на 2 атомарных коммита через staging
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. git blame week-03/index.html — кто и когда менял строку (это ты — привыкай к прослеживаемости)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Репозиторий инициализирован, секреты не в git\n- [ ] Минимум 3 коммита с понятными сообщениями\n- [ ] git status чист после коммита

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. В learning-log выполни git log --oneline -15 — опиши в week-04/REFLECTION.md паттерн своих сообщений
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Исправь 2 слабых commit message через git rebase -i HEAD~3 только если ещё не пушил; иначе — лучше не переписывать историю
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь в корень learning-log расширенный .gitignore (OS, IDE, env, build)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 04 day 1: git init and first commits\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Ветки, слияние и конфликты

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к OSS Workflow Kit

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ветка в Git — просто указатель на коммит. Создать ветку дёшево: git switch -c feature/header ответвляет от текущего состояния, и ты работаешь изолированно, не ломая main. Когда фича готова — слияние (merge) переносит изменения обратно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Fast-forward merge возможен, если main не получил новых коммитов с момента ответвления: указатель main просто «перепрыгнет» на конец feature-ветки. Иначе Git создаёт merge commit — коммит с двумя родителями. git merge --no-ff принудительно создаёт merge commit даже при возможности ff — сохраняет видимость ветки в истории.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конфликт возникает, когда одна и та же строка изменена в обеих ветках. Git вставляет маркеры <<<<<<<, =======, >>>>>>> — ты вручную выбираешь итог, git add, git commit. Конфликт — не катастрофа, а диалог между версиями. git stash временно прячет незакоммиченные правки, если нужно срочно переключить ветку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: представь ветки как параллельные черновики одного текста. main — чистовик, а feature/* — листок, на котором можно свободно экспериментировать, не боясь испортить оригинал. Merge — это не «копирование», а совмещение двух версий текста построчно: там, где правки не пересекаются, Git совмещает их автоматически; там, где обе версии тронули одну и ту же строку, он честно останавливается и просит тебя решить.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: без уверенного понимания веток и конфликтов работа в команде (недели с PR-review, а позже — реальные проекты) превращается в страх перед git merge. Умение спокойно читать маркеры конфликта и осознанно выбирать нужную версию — навык, который используется буквально каждую неделю при слиянии Pull Request.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: ты правишь style.css в feature/dark-theme, добавляя background: #111, а параллельно в main кто-то (или ты сам вчера) поменял тот же селектор на background: #222. При merge Git покажет оба варианта между маркерами — нужно решить, оставить один, объединить логику или переписать заново, а не бездумно удалить «чужой» кусок.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: многие считают конфликт признаком того, что «что-то сломалось». На деле конфликт — это Git защищает тебя от тихой потери чужих изменений; после ручного разрешения обязательно проверь работоспособность кода, а не только факт исчезновения маркеров — этим и займётся сегодняшняя практика.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: ветка — дешёвый черновик; merge — слияние черновика с основной линией.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Pro Git: Ветвление

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай ветку feature/dark-theme, добавь тёмную тему
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Вернись на main, измени тот же файл — спровоцируй конфликт
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Смержи ветку, разреши конфликт вручную
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Попрактикуй git stash при переключении веток с незакоммиченными правками
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Нарисуй схему веток после всех операций
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сравни git merge --no-ff и fast-forward — посмотри историю
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. После разрешения конфликта проверь, что сайт работает
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Конфликт разрешён осознанно, не удалён «всё чужое»\n- [ ] История показывает merge (или осознанный ff)\n- [ ] Понимаю разницу между branch и commit

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай ветку feature/dark-theme, добавь тёмную тему
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Вернись на main, измени тот же файл — спровоцируй конфликт
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Смержи ветку, разреши конфликт вручную
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Попрактикуй git stash при переключении веток с незакоммиченными правками
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 04 day 2: branches merge conflicts\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Коммит в detached HEAD — изменения не на ветке
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • git add . без проверки — случайно добавил .env
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Разрешение конфликта без тестирования — сломанный код в main
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): GitHub и удалённый workflow

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к OSS Workflow Kit

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Локальный Git — половина workflow. Remote (обычно origin на GitHub) — копия репозитория на сервере. git push публикует коммиты; git pull забирает чужие и сливает с твоими. Флаг -u при первом push связывает локальную ветку с удалённой — дальше достаточно git push.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Pull Request — запрос на слияние ветки с описанием изменений. Даже в solo-проекте PR учит дисциплине review: ты смотришь diff глазами «чужого» разработчика до merge. Стратегии merge на GitHub: обычный merge, squash (все коммиты ветки → один), rebase. Squash даёт чистую линейную историю main.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Issues — трекер задач: баг, улучшение, идея. Коммит с fix #12 в сообщении автоматически закрывает issue №12. Fork + upstream — паттерн open source: форкаешь чужой репозиторий, вносишь правки, открываешь PR в оригинал.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: если локальный Git — личный дневник, то GitHub — общая доска, на которую дневник выкладывается для чтения другими. Remote — не «резервная копия в облаке», а отдельная полноценная копия репозитория, с которой твоя локальная версия синхронизируется через push/pull, примерно как два человека редактируют документ и по очереди обмениваются версиями.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: привычка открывать PR даже в одиночном проекте формирует дисциплину, которая станет обязательной в командной разработке — там код почти никогда не попадает в main напрямую, а PR с описанием и review — стандартный процесс в любой компании. Issues и связка fix #12 — тот же язык, на котором ведутся реальные open-source проекты.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: ты создаёшь issue «Кнопка не видна на мобильном», чинишь баг в ветке fix/mobile-button, а в сообщении коммита пишешь fix: button visibility on mobile, closes #12 — после merge issue закроется автоматически, и в истории останется прямая связь «проблема → решение».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички считают, что PR нужен только когда работаешь в команде. На самом деле self-review через PR-диф — это возможность увидеть свой код «со стороны» ещё до того, как он попадёт в основную ветку, и поймать баги, которые не видны в редакторе. Сегодняшняя практика с созданием репозитория, PR и issue тренирует именно этот полный цикл.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: GitHub = remote + социальный слой; PR — разговор о коде до попадания в main.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- GitHub: Hello World

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай репозиторий на GitHub (public), подключи remote
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Запушь main, создай ветку feature/readme, добавь README.md
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Открой Pull Request с описанием изменений
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Смержи PR через GitHub UI (Squash or Merge — изучи разницу)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Создай Issue с багом или улучшением, закрой через коммит fix: ...
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Клонируй репозиторий в другую папку — убедись, что clone работает
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь в README badges (build, license) — заготовка под неделю
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Код на GitHub, локальный и remote синхронизированы\n- [ ] Минимум 1 PR с описанием\n- [ ] README содержит название, описание, как запустить

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай репозиторий на GitHub (public), подключи remote
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Запушь main, создай ветку feature/readme, добавь README.md
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Открой Pull Request с описанием изменений
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Смержи PR через GitHub UI (Squash or Merge — изучи разницу)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 04 day 3: github remote and PR\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): DevTools — Elements и Console

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к OSS Workflow Kit

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Chrome DevTools — рентген твоей страницы. Панель Elements показывает живое DOM-дерево: кликни на узел — увидишь применённые стили, box model, flex/grid overlay. Вкладка Styles перечисляет все CSS-правила с указанием файла и строки; перечёркнутое свойство проиграло в каскаде — ищи победителя выше. Computed — итоговые вычисленные значения после каскада, наследования и браузерных дефолтов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Live-редактирование CSS в DevTools — быстрый эксперимент: подобрал отступ — перенеси в файл. Flex/Grid overlay рисует треки и gap поверх страницы — не гадай, смотри. В Console $0 — ссылка на элемент, выбранный в Elements; мост между визуальным и программным исследованием.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        console.log — базовый вывод; console.table — таблица для массивов объектов; console.group — группировка связанных логов. Уровни warn и error выделяются визуально и фильтруются.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: DevTools — не «дополнительный инструмент для продвинутых», а рентгеновский снимок твоей страницы в реальном времени. Elements показывает не исходный HTML-файл, а живой DOM — то, во что браузер превратил разметку прямо сейчас, включая изменения, сделанные JS. Это принципиально другая картина, чем «View Page Source», который показывает статичный исходник.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: без уверенного владения Elements и Console отладка CSS и будущего JS превращается в метод «тыка» — правишь код, обновляешь страницу, смотришь, повторяешь. С DevTools ты меняешь значение прямо в браузере и мгновенно видишь результат, а находишь причину проблемы за секунды через Computed и Styles. Это основной инструмент во всех последующих неделях, включая отладку JavaScript.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: элемент выглядит не так, как ожидалось — отступ слишком большой. Открываешь Elements, кликаешь на элемент, смотришь Styles: видно зачёркнутое правило margin: 0 из одного файла и победившее margin: 16px из другого, более специфичного селектора. Проблема найдена за 10 секунд, а не за 10 минут просмотра CSS-файлов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: начинающие правят стили прямо в DevTools и считают, что «исправили баг» — но эти изменения исчезают при обновлении страницы, потому что они не сохраняются в файл. DevTools — инструмент для эксперимента и диагностики, а не для постоянного редактирования; найденное значение всегда нужно перенести в исходный CSS-файл, что и требует сегодняшняя практика.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: Styles — «кто перебил?», Computed — «что в итоге?»; overlay — «как устроена сетка?».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Chrome DevTools: Overview

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Открой лендинг, исследуй box model каждой секции в Elements
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Включи flex/grid overlay для layout-контейнеров
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Найди и исправь «лишний» margin через live edit, перенеси в CSS-файл
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. В Console: выбери элемент, измени текст через $0.textContent
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Добавь console.log в будущий JS-файл (заготовка) — проверь вывод
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Используй console.table для массива объектов (заготовка данных)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Найди перечёркнутое свойство в Styles — объясни, почему оно не применилось
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Умею найти источник стиля в панели Styles (файл и строка)\n- [ ] Использовал flex/grid overlay\n- [ ] Знаю разницу Computed vs Styles

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Открой лендинг, исследуй box model каждой секции в Elements
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Включи flex/grid overlay для layout-контейнеров
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Найди и исправь «лишний» margin через live edit, перенеси в CSS-файл
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. В Console: выбери элемент, измени текст через $0.textContent
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 04 day 4: devtools elements console\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): DevTools — Network, Sources, Performance

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к OSS Workflow Kit

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Панель Network показывает каждый HTTP-запрос при загрузке страницы: URL, статус, размер, время. Waterfall — диаграмма «кто за кем»: видно, что блокирует рендер (тяжёлые картинки, синхронные скрипты). Статусы: 200 OK, 304 Not Modified (из кэша), 404 Not Found. При разработке включай Disable cache, иначе видишь устаревшие файлы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Sources — отладка JavaScript: breakpoint останавливает выполнение в точке; step over/into проходят по строкам; watch expressions следят за переменными. Performance записывает профиль: FPS, long tasks, jank при скролле. Lighthouse в DevTools — аудит Performance, Accessibility, Best Practices с конкретными рекомендациями.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Вкладка Application — хранилища браузера: Local Storage, Cookies, Service Workers (обзор на будущее). Тяжёлый ресурс в Network — первый кандидат на оптимизацию: сжатие, WebP, lazy loading.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: если Elements — это рентген структуры страницы, то Network — рентген её загрузки во времени. Waterfall буквально показывает, что происходит от нулевой миллисекунды до полной загрузки: какой запрос начался первым, какой ждал завершения другого, что можно распараллелить. Sources и Performance добавляют временное измерение к тому, что раньше казалось мгновенным «код просто выполнился».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: на неделях с JavaScript breakpoint в Sources станет основным способом отладки — гораздо быстрее и надёжнее, чем расставлять console.log вручную. А умение читать Lighthouse-отчёт понадобится перед сдачей любого проекта курса: это стандартный внешний критерий качества, который проверяющий может запустить за 10 секунд.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: страница грузится 4 секунды. Открываешь Network, видишь в waterfall один PNG весом 3 МБ, который блокирует появление остального контента. Сжимаешь его до WebP весом 200 КБ — время загрузки падает в разы, а Lighthouse Performance-score растёт на 20+ пунктов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички думают, что статус 304 — это ошибка, раз число «не как 200». На самом деле 304 Not Modified означает, что браузер удачно переиспользовал кэш и не скачивал файл заново — это хороший знак производительности, а не проблема. Похожая путаница возникает и с breakpoint в Sources: кажется, что это «то же самое, что console.log, но сложнее» — на деле breakpoint замораживает выполнение целиком, позволяя изучить значения всех переменных в этой точке одновременно, а не только той, что ты решил залогировать заранее. Сегодняшняя практика с анализом waterfall и запуском Lighthouse научит отличать реальные проблемы от нормального поведения браузера.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: Network waterfall — карта загрузки; Lighthouse — чеклист перед сдачей.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Chrome DevTools: Network\n- Chrome DevTools: Performance

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перезагрузи страницу с Network open — проанализируй waterfall
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Найди самый тяжёлый ресурс, оптимизируй (сжатие изображения)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Запусти Lighthouse, сохрани отчёт, исправь 2+ замечания
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. В Sources поставь breakpoint (на inline script или будущий JS)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Запиши Performance profile при скролле — есть ли jank?
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Отфильтруй Network по CSS/JS — оцени общий вес страницы
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь Application → Local Storage (пока пусто — заготовка под неделю 7)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Понимаю статусы 200, 304, 404 в Network\n- [ ] Lighthouse score улучшен после правок\n- [ ] Умею ставить breakpoint и читать call stack

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перезагрузи страницу с Network open — проанализируй waterfall
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Найди самый тяжёлый ресурс, оптимизируй (сжатие изображения)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Запусти Lighthouse, сохрани отчёт, исправь 2+ замечания
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. В Sources поставь breakpoint (на inline script или будущий JS)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 04 day 5: devtools network performance\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Workflow разработчика

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к OSS Workflow Kit

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Workflow — это привычки, которые масштабируются от solo до команды. GitHub Flow — простейший: main всегда deployable, каждая фича в ветке → PR → merge. Git Flow сложнее (develop, release) — избыточен для учебных проектов. Trunk-Based — короткоживущие ветки, частые merge в main — для зрелых команд с CI.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Conventional Commits (feat:, fix:, docs:) — единый язык сообщений; из них генерируется CHANGELOG. Pre-commit checklist: git diff глазами ревьюера, нет ли .env в staging, страница открывается, Lighthouse не упал. Prettier убирает споры о форматировании — один .prettierrc на проект.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        VS Code Git panel, diff view, GitLens — ускоряют ежедневную работу. Code review — не придирка, а передача знаний: даже self-review перед push ловит опечатки и лишние файлы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: workflow — это не набор строгих правил, а привычки, которые снижают трение между «я написал код» и «код безопасно попал в основную ветку». Чем больше шагов автоматизировано (Prettier форматирует, PR-шаблон напоминает о чек-листе), тем меньше энергии тратится на рутину и тем больше остаётся на саму задачу.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: к этому моменту у тебя уже есть Git, ветки, PR и DevTools по отдельности — сегодня они складываются в единый ежедневный ритуал. Именно такой workflow (feature-ветка → self-review → PR → merge) станет твоей рабочей нормой на всех следующих неделях и в первой работе, поэтому его стоит закрепить как автоматизм, а не разовое упражнение.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: перед сегодняшним PR ты открываешь diff и видишь, что случайно закоммитил console.log('test') и файл .DS_Store. Self-review до отправки PR ловит это за 30 секунд — ревьюер (в командной работе) не тратит время на комментарий «убери debug-лог», а видит чистый, готовый к обсуждению код.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: многие считают Prettier и единый стиль коммитов «формальностью для перфекционистов». На практике споры о форматировании (табы vs пробелы, кавычки) съедают время code review впустую — автоматизация этого убирает бессмысленные дискуссии и оставляет разговор только о логике кода. Аналогично с Conventional Commits: кажется, что префикс feat:/fix: — просто украшение, но именно по нему автоматические инструменты позже соберут CHANGELOG без единой ручной правки. Сегодняшняя практика с настройкой Prettier и PR template закрепляет эту автоматизацию раз и навсегда.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: GitHub Flow + Conventional Commits + self-review = профессиональный минимум.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Conventional Commits\n- GitHub Flow

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Переименуй последние коммиты сообщениями в стиле Conventional Commits (если нужно — git rebase осторожно или новые коммиты)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Настрой Prettier в VS Code, отформатируй CSS/HTML
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай PR template в .github/pull_request_template.md
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проведи self-review: открой diff последнего PR глазами ревьюера
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Составь личный чеклист перед каждым push (5 пунктов)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь .prettierrc с базовыми настройками (semi, singleQuote)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Напиши CHANGELOG.md с секцией для недель 1–4
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Коммиты следуют единому стилю сообщений\n- [ ] Prettier настроен и применён\n- [ ] Есть PR template или чеклист в заметках

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Переименуй последние коммиты сообщениями в стиле Conventional Commits (если нужно — git rebase осторожно или новые коммиты)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Настрой Prettier в VS Code, отформатируй CSS/HTML
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Создай PR template в .github/pull_request_template.md
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проведи self-review: открой diff последнего PR глазами ревьюера
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 04 day 6: conventional commits prettier\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Интеграция и практика

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к OSS Workflow Kit

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Инструменты расследования истории: git log — хронология; git diff — разница между состояниями; git show — один коммит целиком; git blame — кто и когда изменил каждую строку файла. Blame не для поиска виноватых, а для понимания контекста: «зачем эта строка появилась?».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Отмена изменений — два разных инструмента. git revert <hash> создаёт новый коммит, отменяющий старый — безопасно для shared main, история не переписывается. git reset --hard откатывает указатель ветки — переписывает историю; только на локальных ветках, никогда на запушенном main без согласования.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        GitHub Pages публикует статику из ветки gh-pages или через Actions — бесплатный live demo для портфолио. git clone в новую папку — тест: «смогу ли я развернуть проект с нуля?» — must-have перед сдачей.

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: в командной работе (и в реальных проектах) reset --hard на общей ветке — одна из немногих Git-операций, которая может по-настоящему навредить чужой работе. Привычка тянуться к revert по умолчанию, а reset использовать только на приватных, ещё не запушенных ветках — защищает и тебя, и коллег. Деплой на GitHub Pages сегодня — это и финальная проверка того, что весь пройденный путь (Git → GitHub → DevTools) складывается в реальный, доступный по ссылке продукт.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: ты закоммитил правку, которая сломала лендинг, и уже запушил её в main. git revert HEAD создаст новый коммит, отменяющий изменения — main снова рабочий, а история честно показывает, что было и что исправлено. Если бы ты сделал reset --hard HEAD~1 и запушил force — коллега, который уже успел стянуть сломанный коммит, оказался бы в противоречивом состоянии.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички считают git clone в новую папку избыточным шагом «раз всё и так работает у меня». На деле это единственный надёжный способ проверить, что в .gitignore не потерялся нужный файл и что проект действительно воспроизводим с нуля — именно это проверяет сегодняшняя практика перед финальным тегом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: revert — безопасная отмена; reset --hard — только локально; clone — финальный тест переносимости.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Pro Git: Отмена изменений\n- GitHub Pages

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Клонируй свой репозиторий в новую папку — проверь, что всё работает
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Найди автора строки через git blame для одного CSS-файла
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Задеплой лендинг на GitHub Pages (branch gh-pages или Actions)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь live URL в DevTools Network и Lighthouse
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Напиши CONTRIBUTING.md с правилами коммитов и веток
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь LICENSE (MIT) и обнови README со скриншотами недель 1–3
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Поставь тег week-04-done на финальный коммит
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Сайт доступен по публичному URL\n- [ ] Clone → open работает без ручных правок\n- [ ] CONTRIBUTING.md или раздел в README описывает workflow

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Клонируй свой репозиторий в новую папку — проверь, что всё работает
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Найди автора строки через git blame для одного CSS-файла
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Задеплой лендинг на GitHub Pages (branch gh-pages или Actions)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь live URL в DevTools Network и Lighthouse
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 04 day 7: github pages contributing\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Open-source мини-проект — публичный репозиторий с лендингом, полным Git-историей и деплоем.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подробное описание: docs/projects.md — Неделя 4

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Требования:\n- Минимум 10 коммитов, 2+ ветки, 1 merged PR\n- README, .gitignore, LICENSE (MIT)\n- GitHub Pages или аналог — live demo\n- CONTRIBUTING.md с Conventional Commits

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] История коммитов читаема и атомарна\n- [ ] PR с описанием и self-review\n- [ ] Live demo работает\n- [ ] Нет секретов и лишних файлов в репозитории\n- [ ] README с badges, скриншотами проектов недель 1–3\n- [ ] ≥ 2 feature-ветки, осознанный выбор merge vs rebase\n- [ ] CHANGELOG.md с записями по Conventional Commits\n- [ ] GitHub Pages деплоит week-03 лендинг по публичному URL\n- [ ] Тег week-04-done на финальном коммите

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • В чём разница git add, git commit, git push?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как отменить последний коммит, не потеряв изменения?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что показывает git log --oneline --graph?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как найти, какой CSS-файл задаёт конкретное свойство в DevTools?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Могу ли я объяснить flow: branch → commit → push → PR → merge?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **OSS Workflow Kit** в `learning-log/week-04/`, осмысленная Git-история, тег `week-04-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nПрофессиональный Git-workflow и DevTools\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-04-day-1", "label": "День 1 (Mon): Git — ревизия основ + git log как инструмент"}, {"id": "week-04-day-2", "label": "День 2 (Tue): Ветки, слияние и конфликты"}, {"id": "week-04-day-3", "label": "День 3 (Wed): GitHub и удалённый workflow"}, {"id": "week-04-day-4", "label": "День 4 (Thu): DevTools — Elements и Console"}, {"id": "week-04-day-5", "label": "День 5 (Fri): DevTools — Network, Sources, Performance"}, {"id": "week-04-day-6", "label": "День 6 (Sat): Workflow разработчика"}, {"id": "week-04-day-7", "label": "День 7 (Sun): Интеграция и практика"}, {"id": "week-04-project", "label": "Проект недели"}, {"id": "week-04-review", "label": "Ревью-чеклист"}], "text": "Неделя 4: Git Advanced, GitHub workflow, DevTools Цель недели: углубить Git (ветки, merge, rebase, PR), оформить learning-log как OSS-проект, освоить DevTools. Предусловие: Git с недели 1 — репозиторий learning-log уже существует, ежедневные коммиты — привычка. Литература: Scott Chacon, Ben Straub «Pro Git» ( git-scm.com/book ), GitHub Docs , Chrome DevTools Docs , Conventional Commits , Oh Shit, Git!?! — экстренные сценарии Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-04/ День 1 (Mon): Git — ревизия основ + git log как инструмент Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к OSS Workflow Kit Теория Перед углублением в ветки стоит …"} \ No newline at end of file diff --git a/docs/weeks/05.json b/docs/weeks/05.json index ffae1a0..b83a1ca 100644 --- a/docs/weeks/05.json +++ b/docs/weeks/05.json @@ -1 +1 @@ -{"id": "week-05", "title": "JavaScript", "fullTitle": "Неделя 5: JavaScript — переменные, типы, функции, массивы", "html": "

                                                                                                                                                                                                                        Неделя 5: JavaScript — переменные, типы, функции, массивы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: заложить фундамент JavaScript — синтаксис, типы данных, функции и работа с массивами.\nЛитература: learn.javascript.ru, Kyle Simpson «You Don't Know JS» (Scope & Closures, Types & Grammar), MDN JavaScript Guide, JavaScript.info — углублённые объяснения, Eloquent JavaScript (гл. 1–4)

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md\nGit: минимум 1 осмысленный коммит каждый день в learning-log/week-05/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Введение и переменные

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Console Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        JavaScript в браузере — язык, который оживляет страницу. Браузер парсит HTML, строит DOM, затем загружает и выполняет JS в основном потоке (main thread). Код идёт сверху вниз; тяжёлый цикл блокирует UI — кнопки не реагируют, пока цикл не завершится.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подключение: <script defer src=\"app.js\"> — скрипт грузится параллельно с HTML и выполняется после парсинга, не блокируя рендер. type=\"module\" — ES-модули с изолированной областью видимости и import/export. Переменные: let — изменяемая; const — нельзя переприсвоить, но объект по const можно мутировать (менять свойства). var — устарел: function scope и поднятие (hoisting) создают ловушки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Temporal Dead Zone (TDZ): let/const недоступны до строки объявления — ReferenceError вместо тихого undefined. Строгий режим 'use strict' ловит опечатки в именах переменных и небезопасные приёмы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: defer + let/const + strict mode — современный старт без сюрпризов hoisting.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Введение — как выполняется JS в браузере\n- learn.javascript.ru: var — разница let/const/var и TDZ

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай app.js, подключи к HTML через defer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Объяви переменные let и const разных типов, выведи в console
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Попробуй переприсвоить const объект — измени свойство vs переприсвоение
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Включи 'use strict', спровоцируй ошибку с необъявленной переменной
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Настрой VS Code: ESLint или встроенную проверку синтаксиса
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай папку week-05/ и файл app.js — старт проекта недели
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь console.log с шаблонной строкой и своим именем
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Используются только let/const, не var\n- [ ] Скрипт подключён корректно, нет ошибок в Console\n- [ ] Понимаю разницу переприсвоения и мутации объекта

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай app.js, подключи к HTML через defer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Объяви переменные let и const разных типов, выведи в console
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Попробуй переприсвоить const объект — измени свойство vs переприсвоение
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Включи 'use strict', спровоцируй ошибку с необъявленной переменной
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 05 day 1: js intro variables\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Типы данных и операторы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Console Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        JavaScript — динамически типизированный язык: тип определяется значением, а не объявлением. Примитивыnumber, string, boolean, null, undefined, symbol, bigint — неизменяемы: str.toUpperCase() возвращает новую строку, оригинал не трогает. Всё остальное — объекты (массивы, функции, plain objects).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        typeof возвращает строку с типом; ловушка: typeof null === 'object' — исторический баг, проверяй value === null. null — намеренное «пусто»; undefined — переменная не инициализирована. Сравнение == приводит типы неявно ('5' == 5 → true); === сравнивает значение и тип — используй всегда в новом коде.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Template literals `Привет, ${name}!` поддерживают интерполяцию и многострочность — чище конкатенации через +. Truthy/falsy: 0, '', null, undefined, NaN, false — falsy; всё остальное truthy.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: === вместо ==; примитивы неизменяемы; nullundefined по смыслу.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Типы — примитивы и объекты\n- learn.javascript.ru: Операторы — арифметика, сравнение, логика

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Напиши функцию describeType(value) — возвращает строку с typeof и значением
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Таблица сравнений: 0 == false, '' == false, null == undefined — предскажи, проверь
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Калькулятор в Console: сложение, деление, остаток, возведение в степень
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Конвертер температуры °C → °F с template literal в выводе
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Используй только === в новом коде
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Проверь Number.isNaN(NaN) vs NaN === NaN — зафиксируй в комментарии
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Создай таблицу truthy/falsy значений в notes.md
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Все сравнения через ===\n- [ ] Нет неявных приведений без понимания\n- [ ] Template literals для интерполяции строк

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Напиши функцию describeType(value) — возвращает строку с typeof и значением
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Таблица сравнений: 0 == false, '' == false, null == undefined — предскажи, проверь
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Калькулятор в Console: сложение, деление, остаток, возведение в степень
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Конвертер температуры °C → °F с template literal в выводе
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 05 day 2: types and operators\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • typeof null === 'object' — исторический баг
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • NaN === NaN → false; проверка через Number.isNaN()
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Сложение строки и числа: '5' + 3'53'
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): Условия и циклы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Console Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Условия направляют поток выполнения. if/else — базовая развилка; тернарный оператор условие ? a : b — для простых выборов в одну строку, не для вложенных лабиринтов. switch сравнивает значение с case; без break выполнение проваливается в следующий case — частая ошибка новичков.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Циклы: while — пока условие true; do...while — минимум одна итерация; for — классика с счётчиком. break выходит из цикла, continue — пропускает текущую итерацию. Для массивов позже предпочтительнее for...of, но классический for нужен для индексов и обратного обхода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Early return в функциях уменьшает вложенность: вместо if (ok) { ... много кода }if (!ok) return; и дальше линейный код. Truthy/falsy позволяют писать if (name) вместо if (name !== '' && name !== null) — но понимай, что 0 и '' тоже falsy.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: switch без break — провал; early return — меньше вложенных if.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Условное ветвление\n- learn.javascript.ru: Циклы — while, do...while, for

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Программа «FizzBuzz» (1–100) — вывод в Console
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Калькулятор оценок: число → буква (A/B/C/D/F) через switch
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Таблица умножения 10×10 в виде строки в Console
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Найди сумму чисел 1..N через for
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг: замени вложенные if на early return где уместно
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь валидацию ввода в FizzBuzz — обработай N <= 0
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Перепиши один блок на тернарный оператор — оцени читаемость
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] FizzBuzz работает корректно\n- [ ] Нет бесконечных циклов\n- [ ] Код читаем, переменные с понятными именами

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Программа «FizzBuzz» (1–100) — вывод в Console
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Калькулятор оценок: число → буква (A/B/C/D/F) через switch
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Таблица умножения 10×10 в виде строки в Console
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Найди сумму чисел 1..N через for
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 05 day 3: conditions and loops\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): Функции

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Console Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функция — именованный блок кода, который можно вызывать многократно. Declaration (function foo() {}) поднимается (hoisting) — доступна до строки объявления. Expression (const foo = function() {}) — нет. Arrow functions (const foo = () => {}) — короткий синтаксис; неявный return при () => выражение без фигурных скобок.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Параметры и аргументы: параметры в объявлении, аргументы при вызове. Значения по умолчанию (greeting = 'Привет') и rest (...numbers) делают сигнатуру гибкой. Чистая функция — одинаковый вход всегда даёт одинаковый выход, без побочных эффектов (изменения внешних переменных, DOM, сети). Такие функции проще тестировать и переиспользовать.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Arrow functions не имеют своего this — важно для методов объектов (неделя 6). Принцип SRP (Single Responsibility): одна функция — одна задача; calculateTotal, не doEverything.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: чистые функции + SRP = код, который можно читать, тестировать и переиспользовать.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Функции

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Напиши greet(name, greeting = 'Привет') — declaration
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перепиши как arrow function; сравни поведение this (пока без углубления)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Функция sum(...numbers) — сумма произвольного числа аргументов
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. isEven(n), isPrime(n), factorial(n) — чистые функции
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Организуй функции в отдельный файл utils.js (подключение пока без modules)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь JSDoc к factorial — опиши параметр и возврат
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Напиши generateId() — уникальный id на основе Date.now() и случайности
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Минимум 5 переиспользуемых функций\n- [ ] Default parameters и rest использованы\n- [ ] Функции делают одну вещь (SRP)

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Напиши greet(name, greeting = 'Привет') — declaration
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перепиши как arrow function; сравни поведение this (пока без углубления)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Функция sum(...numbers) — сумма произвольного числа аргументов
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. isEven(n), isPrime(n), factorial(n) — чистые функции
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 05 day 4: functions and utils\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Массивы — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~45м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Console Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Массив — упорядоченная коллекция значений с числовыми индексами (с 0). Массивы мутабельны: push/pop с конца, shift/unshift с начала. splice изменяет массив на месте (удаляет/вставляет); slice возвращает копию участка, оригинал не трогает — частая путаница новичков.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Поиск: indexOf, includes. Spread [...arr] создаёт shallow copy — вложенные объекты остаются общими ссылками. for...of перебирает значения; for...in по массиву даёт индексы как строки — для массивов не используй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Свойство length можно менять вручную — массив обрежется, но это редкий приём. Модель задачи {id, title, done} в массиве — фундамент Todo-приложения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: slice — копия без мутации; splice — мутация; for...of, не for...in.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Массивы

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Список покупок: добавление, удаление, вывод через for...of
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Найди min/max в массиве чисел без Math.min на входе массива
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Удали дубликаты из массива (без Set — через цикл; потом с Set)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Объедини два массива через spread
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Реверс массива без .reverse() — через цикл
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай массив задач-заготовок {id, title, done} для Todo
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Сравни slice и splice на одном массиве — выведи до/после
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Понимаю разницу slice и splice\n- [ ] Итерация через for...of, не for...in для массивов\n- [ ] Spread не мутирует оригинал

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Список покупок: добавление, удаление, вывод через for...of
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Найди min/max в массиве чисел без Math.min на входе массива
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Удали дубликаты из массива (без Set — через цикл; потом с Set)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Объедини два массива через spread
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 05 day 5: arrays basics\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Методы массивов

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Console Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Методы массивов высокого порядка — рабочая лошадка современного JS. map трансформирует каждый элемент и возвращает новый массив. filter отбирает по условию. reduce сворачивает массив в одно значение: сумма, группировка, flatten. find / findIndex — первый подходящий элемент. some / every — проверки «хотя бы один» / «все».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        forEach выполняет действие для каждого элемента, но ничего не возвращает — для побочных эффектов (логирование). Нужен новый массив — map. Цепочки .filter().map().reduce() читаются как конвейер данных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушка sort: без compare-функции сортирует как строки[10, 5, 40][10, 40, 5]. Для чисел: (a, b) => a - b. Мутирует исходный массив — сначала [...arr].sort().

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: map/filter/reduce — декларативный стиль; sort всегда с compare-функцией для чисел.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Методы массивов

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Массив пользователей {name, age}: фильтр 18+, map в имена
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Сумма цен корзины через reduce
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Найди первый товар дороже 1000 через find
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь, все ли оценки ≥ 3 через every
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Отсортируй числа [10, 5, 40, 25] правильно: (a, b) => a - b
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Цепочка: фильтр активных задач → map в заголовки → join в строку
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Группировка задач по done через reduce
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Использованы map, filter, reduce в реальных задачах\n- [ ] Сортировка чисел корректна\n- [ ] Цепочка из 3+ методов в одной задаче

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Массив пользователей {name, age}: фильтр 18+, map в имена
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Сумма цен корзины через reduce
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Найди первый товар дороже 1000 через find
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь, все ли оценки ≥ 3 через every
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 05 day 6: array methods\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Мини-проект и закрепление

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~45м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Console Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Отладка — навык не менее важный, чем написание кода. Stack trace в Console показывает цепочку вызовов: читается снизу вверх — последний вызов (где упало) наверху. debugger в коде останавливает выполнение, если DevTools открыты — альтернатива ручному breakpoint в Sources.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Разбиение на функции (addTask, removeTask, listTasks) и файлы упрощает отладку: сломалось удаление — смотришь одну функцию, не весь скрипт. JSDoc (@param, @returns) документирует сигнатуру — IDE подсказывает типы до перехода на TypeScript.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Консольное Todo без DOM — чистая тренировка data layer: массив + функции. На неделе 6 тот же массив «оживят» через renderTasks().

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: stack trace + breakpoint > десять console.log; функции — единицы отладки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Chrome DevTools: JavaScript

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Консольное приложение «Todo List» (массив + функции add/remove/list)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Поиск по задачам через filter
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Статистика: всего, выполнено, в процессе через reduce
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Отладь с breakpoint в DevTools Sources
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Напиши JSDoc для 3 ключевых функций
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь фильтр по статусу done / active
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Финальный коммит feat: todo manager core и тег week-05-done
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Todo list работает в Console без DOM\n- [ ] Код разбит на логические функции\n- [ ] Отладка через breakpoint, не только console.log

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Консольное приложение «Todo List» (массив + функции add/remove/list)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Поиск по задачам через filter
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Статистика: всего, выполнено, в процессе через reduce
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Отладь с breakpoint в DevTools Sources
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 05 day 7: console todo project\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Консольный менеджер задач — JS-приложение без DOM, управляемое из DevTools Console.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подробное описание: docs/projects.md — Неделя 5

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции: добавить задачу, удалить по id, отметить выполненной, фильтр по статусу, статистика.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] Массив объектов {id, title, done, createdAt}\n- [ ] Использованы map, filter, reduce, find\n- [ ] Минимум 8 функций, чистые где возможно\n- [ ] Код в репозитории с коммитом feat: todo manager core\n- [ ] CRUD полный: create, read, update (toggle done), delete\n- [ ] Фильтры: все / активные / выполненные\n- [ ] Статистика через reduce: всего, done, pending\n- [ ] Папка week-05/ с README и примером вызова функций в Console\n- [ ] Тег week-05-done на финальном коммите

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Разница let, const и почему не var?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что вернёт typeof NaN и как проверить NaN?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Разница map и forEach?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как отсортировать массив чисел по возрастанию?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Могу ли я написать FizzBuzz и объяснить каждую ветку?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Console Task Manager** в `learning-log/week-05/`, осмысленная Git-история, тег `week-05-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nJavaScript: типы, функции, массивы, чистый синтаксис\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-05-day-1", "label": "День 1 (Mon): Введение и переменные"}, {"id": "week-05-day-2", "label": "День 2 (Tue): Типы данных и операторы"}, {"id": "week-05-day-3", "label": "День 3 (Wed): Условия и циклы"}, {"id": "week-05-day-4", "label": "День 4 (Thu): Функции"}, {"id": "week-05-day-5", "label": "День 5 (Fri): Массивы — основы"}, {"id": "week-05-day-6", "label": "День 6 (Sat): Методы массивов"}, {"id": "week-05-day-7", "label": "День 7 (Sun): Мини-проект и закрепление"}, {"id": "week-05-project", "label": "Проект недели"}, {"id": "week-05-review", "label": "Ревью-чеклист"}], "text": "Неделя 5: JavaScript — переменные, типы, функции, массивы Цель недели: заложить фундамент JavaScript — синтаксис, типы данных, функции и работа с массивами. Литература: learn.javascript.ru , Kyle Simpson «You Don't Know JS» (Scope & Closures, Types & Grammar), MDN JavaScript Guide , JavaScript.info — углублённые объяснения, Eloquent JavaScript (гл. 1–4) Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-05/ День 1 (Mon): Введение и переменные Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Console Task Manager Теория JavaScript в браузере — язык, который оживляет страницу. Браузер парсит HTML, строит DOM, затем загружает и выполняе…"} \ No newline at end of file +{"id": "week-05", "title": "JavaScript", "fullTitle": "Неделя 5: JavaScript — переменные, типы, функции, массивы", "html": "

                                                                                                                                                                                                                        Неделя 5: JavaScript — переменные, типы, функции, массивы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: заложить фундамент JavaScript — синтаксис, типы данных, функции и работа с массивами.\nЛитература: learn.javascript.ru, Kyle Simpson «You Don't Know JS» (Scope & Closures, Types & Grammar), MDN JavaScript Guide, JavaScript.info — углублённые объяснения, Eloquent JavaScript (гл. 1–4)

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md\nGit: минимум 1 осмысленный коммит каждый день в learning-log/week-05/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Введение и переменные

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Console Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        JavaScript в браузере — язык, который оживляет страницу. Браузер парсит HTML, строит DOM, затем загружает и выполняет JS в основном потоке (main thread). Код идёт сверху вниз; тяжёлый цикл блокирует UI — кнопки не реагируют, пока цикл не завершится.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подключение: <script defer src=\"app.js\"> — скрипт грузится параллельно с HTML и выполняется после парсинга, не блокируя рендер. type=\"module\" — ES-модули с изолированной областью видимости и import/export. Переменные: let — изменяемая; const — нельзя переприсвоить, но объект по const можно мутировать (менять свойства). var — устарел: function scope и поднятие (hoisting) создают ловушки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Temporal Dead Zone (TDZ): let/const недоступны до строки объявления — ReferenceError вместо тихого undefined. Строгий режим 'use strict' ловит опечатки в именах переменных и небезопасные приёмы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: представь браузер как читателя, который сначала бегло просматривает весь файл (парсинг и «поднятие» объявлений), а только потом читает его вдумчиво сверху вниз (выполнение). var при беглом просмотре сразу создаёт переменную со значением undefined — поэтому обращение к ней до объявления не падает с ошибкой, а тихо возвращает undefined, маскируя баг. let/const в TDZ ведут себя строже: переменная «зарезервирована», но трогать её нельзя — это осознанное решение авторов языка сделать ошибки видимыми сразу.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: от этого фундамента зависит вообще всё в JS — функции, объекты, DOM-события в следующих неделях объявляются через let/const, и понимание того, когда переменная «жива», а когда ещё нет, объясняет добрую половину загадочных багов новичков («почему тут undefined, а не моё значение»).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: console.log(x); var x = 5; выведет undefined без ошибки — hoisting поднял объявление, но не присваивание. Замени на let: console.log(x); let x = 5; — получишь ReferenceError: Cannot access 'x' before initialization, потому что x в TDZ до строки объявления.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: начинающие думают, что const делает объект неизменяемым целиком. На самом деле const запрещает только переприсвоение самой переменной (user = {} — ошибка), а свойства объекта менять можно (user.age = 26 — сработает). Это первое, что стоит проверить в сегодняшней практике на шаге с мутацией const-объекта.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: defer + let/const + strict mode — современный старт без сюрпризов hoisting.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Введение — как выполняется JS в браузере\n- learn.javascript.ru: var — разница let/const/var и TDZ

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай app.js, подключи к HTML через defer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Объяви переменные let и const разных типов, выведи в console
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Попробуй переприсвоить const объект — измени свойство vs переприсвоение
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Включи 'use strict', спровоцируй ошибку с необъявленной переменной
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Настрой VS Code: ESLint или встроенную проверку синтаксиса
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай папку week-05/ и файл app.js — старт проекта недели
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь console.log с шаблонной строкой и своим именем
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Используются только let/const, не var\n- [ ] Скрипт подключён корректно, нет ошибок в Console\n- [ ] Понимаю разницу переприсвоения и мутации объекта

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай app.js, подключи к HTML через defer
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Объяви переменные let и const разных типов, выведи в console
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Попробуй переприсвоить const объект — измени свойство vs переприсвоение
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Включи 'use strict', спровоцируй ошибку с необъявленной переменной
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 05 day 1: js intro variables\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Типы данных и операторы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Console Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        JavaScript — динамически типизированный язык: тип определяется значением, а не объявлением. Примитивыnumber, string, boolean, null, undefined, symbol, bigint — неизменяемы: str.toUpperCase() возвращает новую строку, оригинал не трогает. Всё остальное — объекты (массивы, функции, plain objects).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        typeof возвращает строку с типом; ловушка: typeof null === 'object' — исторический баг, проверяй value === null. null — намеренное «пусто»; undefined — переменная не инициализирована. Сравнение == приводит типы неявно ('5' == 5 → true); === сравнивает значение и тип — используй всегда в новом коде.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Template literals `Привет, ${name}!` поддерживают интерполяцию и многострочность — чище конкатенации через +. Truthy/falsy: 0, '', null, undefined, NaN, false — falsy; всё остальное truthy.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: думай о == как о переводчике, который сначала пытается «подогнать» два разных языка (типа) под общий знаменатель, а потом сравнивает — и этот перевод не всегда очевиден. === ничего не переводит: сравнивает как есть, тип и значение. Именно поэтому опытные разработчики почти никогда не используют == — предсказуемость важнее «экономии» одного символа.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: динамическая типизация — источник и гибкости, и большинства багов JS. Понимание того, где JS молча приводит типы (в сравнении, в сложении, в условиях if), — фундамент для отладки на всех следующих неделях, включая работу с формами (неделя 6-7), где данные из инпутов всегда приходят строками.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: '5' == 5 вернёт true, потому что == приводит строку к числу перед сравнением. Но '5' === 5 вернёт false — разные типы. Похожая ловушка: [] == false даёт true из-за цепочки неявных приведений, тогда как [] === false — однозначно false. Такие примеры стоит проверить вживую в Console, а не запоминать как правило.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: многие считают null и undefined взаимозаменяемыми синонимами «пусто». На деле undefined — это то, что даёт сам JS, когда значения ещё нет (необъявленная переменная, отсутствующее свойство объекта, функция без return), а null — то, что программист осознанно присваивает, чтобы сказать «здесь намеренно ничего нет». Различие пригодится при проектировании функций в сегодняшней практике.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: === вместо ==; примитивы неизменяемы; nullundefined по смыслу.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Типы — примитивы и объекты\n- learn.javascript.ru: Операторы — арифметика, сравнение, логика

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Напиши функцию describeType(value) — возвращает строку с typeof и значением
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Таблица сравнений: 0 == false, '' == false, null == undefined — предскажи, проверь
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Калькулятор в Console: сложение, деление, остаток, возведение в степень
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Конвертер температуры °C → °F с template literal в выводе
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Используй только === в новом коде
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Проверь Number.isNaN(NaN) vs NaN === NaN — зафиксируй в комментарии
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Создай таблицу truthy/falsy значений в notes.md
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Все сравнения через ===\n- [ ] Нет неявных приведений без понимания\n- [ ] Template literals для интерполяции строк

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Напиши функцию describeType(value) — возвращает строку с typeof и значением
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Таблица сравнений: 0 == false, '' == false, null == undefined — предскажи, проверь
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Калькулятор в Console: сложение, деление, остаток, возведение в степень
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Конвертер температуры °C → °F с template literal в выводе
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 05 day 2: types and operators\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • typeof null === 'object' — исторический баг
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • NaN === NaN → false; проверка через Number.isNaN()
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Сложение строки и числа: '5' + 3'53'
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): Условия и циклы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Console Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Условия направляют поток выполнения. if/else — базовая развилка; тернарный оператор условие ? a : b — для простых выборов в одну строку, не для вложенных лабиринтов. switch сравнивает значение с case; без break выполнение проваливается в следующий case — частая ошибка новичков.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Циклы: while — пока условие true; do...while — минимум одна итерация; for — классика с счётчиком. break выходит из цикла, continue — пропускает текущую итерацию. Для массивов позже предпочтительнее for...of, но классический for нужен для индексов и обратного обхода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Early return в функциях уменьшает вложенность: вместо if (ok) { ... много кода }if (!ok) return; и дальше линейный код. Truthy/falsy позволяют писать if (name) вместо if (name !== '' && name !== null) — но понимай, что 0 и '' тоже falsy.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: условия и циклы — это то, что превращает статичный код в программу, способную принимать решения и повторять действия. Если переменные и типы — это «существительные» языка программирования, то if, for, while — его «глаголы»: они управляют потоком выполнения, решая, какой код выполнится, а какой — нет, и сколько раз.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: без уверенного владения циклами невозможна работа с массивами (уже завтра) и DOM-списками (неделя 6) — рендеринг списка задач в интерфейсе буквально означает «пройтись циклом по массиву и создать элемент для каждого». Early return как стиль тоже останется с тобой навсегда — это один из главных приёмов для читаемого кода в любом языке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: классическая ошибка switch без breakcase 'A': console.log('Отлично'); case 'B': console.log('Хорошо'); — при 'A' выведет оба сообщения, потому что выполнение «проваливается» в следующий case. Добавление break после каждого блока — обязательная привычка, если явно не нужен fallthrough.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички считают тернарный оператор «более крутой» заменой любому if/else и начинают вкладывать тернарники друг в друга (a ? b : c ? d : e) — получается код, который сложнее читать, чем обычный if. Правило простое: тернарник — для одной простой развилки в присваивании или выводе, if/else — для всего остального, включая ветвление в сегодняшнем FizzBuzz.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: switch без break — провал; early return — меньше вложенных if.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Условное ветвление\n- learn.javascript.ru: Циклы — while, do...while, for

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Программа «FizzBuzz» (1–100) — вывод в Console
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Калькулятор оценок: число → буква (A/B/C/D/F) через switch
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Таблица умножения 10×10 в виде строки в Console
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Найди сумму чисел 1..N через for
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг: замени вложенные if на early return где уместно
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь валидацию ввода в FizzBuzz — обработай N <= 0
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Перепиши один блок на тернарный оператор — оцени читаемость
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] FizzBuzz работает корректно\n- [ ] Нет бесконечных циклов\n- [ ] Код читаем, переменные с понятными именами

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Программа «FizzBuzz» (1–100) — вывод в Console
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Калькулятор оценок: число → буква (A/B/C/D/F) через switch
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Таблица умножения 10×10 в виде строки в Console
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Найди сумму чисел 1..N через for
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 05 day 3: conditions and loops\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): Функции

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Console Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функция — именованный блок кода, который можно вызывать многократно. Declaration (function foo() {}) поднимается (hoisting) — доступна до строки объявления. Expression (const foo = function() {}) — нет. Arrow functions (const foo = () => {}) — короткий синтаксис; неявный return при () => выражение без фигурных скобок.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Параметры и аргументы: параметры в объявлении, аргументы при вызове. Значения по умолчанию (greeting = 'Привет') и rest (...numbers) делают сигнатуру гибкой. Чистая функция — одинаковый вход всегда даёт одинаковый выход, без побочных эффектов (изменения внешних переменных, DOM, сети). Такие функции проще тестировать и переиспользовать.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Arrow functions не имеют своего this — важно для методов объектов (неделя 6). Принцип SRP (Single Responsibility): одна функция — одна задача; calculateTotal, не doEverything.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: функция — это маленькая машина: на входе параметры, внутри — чёрный ящик преобразований, на выходе — результат через return. Чистая функция не имеет «утечек» наружу: не трогает глобальные переменные, не меняет DOM, не делает сетевых запросов — только считает и возвращает. Такую машину легко тестировать отдельно от всей программы и переиспользовать где угодно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: буквально весь курс дальше строится на функциях — методы массивов (завтра), обработчики событий (неделя 6), запросы к API (неделя 7). Разделение на маленькие чистые функции с одной ответственностью — это ровно то, что отличает читаемый проект от «одного гигантского файла, в котором страшно что-то менять».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: function addToCartAndUpdateUIAndSendAnalytics(item) {...} — это функция с тремя ответственностями сразу, её сложно тестировать и ещё сложнее переиспользовать. Разбив на addToCart(cart, item) (чистая, возвращает новый массив), renderCart(cart) (рисует DOM) и trackEvent(name) (аналитика), получаешь три независимых, понятных куска, каждый из которых можно менять не боясь сломать остальные.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички думают, что arrow function — это просто «более короткий синтаксис» без разницы в поведении. На деле у arrow function нет собственного this — она берёт его из внешнего контекста, что критично для методов объектов и обработчиков событий на неделе 6, где ошибка с this — одна из самых частых причин «код не работает, а ошибки нет». Ещё одна тонкость: неявный return в стрелочной функции работает только без фигурных скобок — стоит добавить {}, и return придётся писать явно, иначе функция вернёт undefined.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: чистые функции + SRP = код, который можно читать, тестировать и переиспользовать.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Функции

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Напиши greet(name, greeting = 'Привет') — declaration
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перепиши как arrow function; сравни поведение this (пока без углубления)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Функция sum(...numbers) — сумма произвольного числа аргументов
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. isEven(n), isPrime(n), factorial(n) — чистые функции
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Организуй функции в отдельный файл utils.js (подключение пока без modules)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь JSDoc к factorial — опиши параметр и возврат
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Напиши generateId() — уникальный id на основе Date.now() и случайности
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Минимум 5 переиспользуемых функций\n- [ ] Default parameters и rest использованы\n- [ ] Функции делают одну вещь (SRP)

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Напиши greet(name, greeting = 'Привет') — declaration
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перепиши как arrow function; сравни поведение this (пока без углубления)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Функция sum(...numbers) — сумма произвольного числа аргументов
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. isEven(n), isPrime(n), factorial(n) — чистые функции
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 05 day 4: functions and utils\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Массивы — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Console Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Массив — упорядоченная коллекция значений с числовыми индексами (с 0). Массивы мутабельны: push/pop с конца, shift/unshift с начала. splice изменяет массив на месте (удаляет/вставляет); slice возвращает копию участка, оригинал не трогает — частая путаница новичков.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Поиск: indexOf, includes. Spread [...arr] создаёт shallow copy — вложенные объекты остаются общими ссылками. for...of перебирает значения; for...in по массиву даёт индексы как строки — для массивов не используй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Свойство length можно менять вручную — массив обрежется, но это редкий приём. Модель задачи {id, title, done} в массиве — фундамент Todo-приложения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: массив удобно представлять как пронумерованный список ящиков в ряд: у каждого ящика есть номер (индекс) начиная с 0, и ты можешь взять содержимое конкретного ящика напрямую, зная номер, вместо того чтобы перебирать все по очереди. Методы push/pop/shift/unshift работают только с крайними ящиками ряда — поэтому они быстрые; вставка в середину (splice) требует сдвинуть все ящики после неё.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: массив объектов {id, title, done} — это ровно та структура данных, вокруг которой построен весь Console Task Manager этой недели, а затем DOM Todo App на неделе 6. Понимание разницы между мутацией (splice, push) и созданием копии (slice, spread) станет критичным при работе с состоянием приложения — случайная мутация массива, который «где-то ещё используется», один из самых коварных багов в JS.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: const copy = arr.slice(1, 3) возвращает новый массив с элементами с индекса 1 по 2, не трогая arr. А arr.splice(1, 2) удаляет те же элементы из самого arr и возвращает удалённые — оригинал изменится. Спутав эти методы, легко случайно испортить данные, которые нужны были дальше в неизменном виде.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички используют for...in для перебора массивов по аналогии с объектами. Но for...in перебирает индексы как строки и может включить лишние перечисляемые свойства, если они есть у массива — для массивов правильный выбор for...of (по значениям) или классический for (когда нужен индекс). Ещё одна ловушка: [...arr] создаёт новый массив, но если внутри лежат объекты, копируются только ссылки на них — изменение поля вложенного объекта в копии отразится и на оригинале. Сегодняшняя практика со списком покупок построена именно на for...of.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: slice — копия без мутации; splice — мутация; for...of, не for...in.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Массивы

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Список покупок: добавление, удаление, вывод через for...of
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Найди min/max в массиве чисел без Math.min на входе массива
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Удали дубликаты из массива (без Set — через цикл; потом с Set)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Объедини два массива через spread
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Реверс массива без .reverse() — через цикл
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай массив задач-заготовок {id, title, done} для Todo
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Сравни slice и splice на одном массиве — выведи до/после
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Понимаю разницу slice и splice\n- [ ] Итерация через for...of, не for...in для массивов\n- [ ] Spread не мутирует оригинал

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Список покупок: добавление, удаление, вывод через for...of
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Найди min/max в массиве чисел без Math.min на входе массива
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Удали дубликаты из массива (без Set — через цикл; потом с Set)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Объедини два массива через spread
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 05 day 5: arrays basics\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Методы массивов

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Console Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Методы массивов высокого порядка — рабочая лошадка современного JS. map трансформирует каждый элемент и возвращает новый массив. filter отбирает по условию. reduce сворачивает массив в одно значение: сумма, группировка, flatten. find / findIndex — первый подходящий элемент. some / every — проверки «хотя бы один» / «все».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        forEach выполняет действие для каждого элемента, но ничего не возвращает — для побочных эффектов (логирование). Нужен новый массив — map. Цепочки .filter().map().reduce() читаются как конвейер данных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушка sort: без compare-функции сортирует как строки[10, 5, 40][10, 40, 5]. Для чисел: (a, b) => a - b. Мутирует исходный массив — сначала [...arr].sort().

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: map/filter/reduce — это язык, на котором пишется современный JavaScript и особенно React (когда дойдёшь до фреймворков): рендеринг списка компонентов почти всегда начинается с .map(). Умение читать и писать цепочки этих методов вместо ручных циклов резко повышает читаемость и снижает количество багов вроде забытого break или неправильного индекса.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: задача «сумма цен товаров дороже 100» императивно — это цикл с условием и накопительной переменной. Декларативно: items.filter(i => i.price > 100).reduce((sum, i) => sum + i.price, 0) — три слова описывают весь алгоритм, и почти невозможно ошибиться в границах цикла, потому что их просто нет.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички путают forEach с map, ожидая, что forEach тоже вернёт новый массив — но forEach всегда возвращает undefined, он предназначен только для побочных эффектов (например, логирования), а не для трансформации данных. Похожая путаница со sort: он мутирует исходный массив, поэтому если оригинал ещё нужен неотсортированным, всегда работай с копией через [...arr].sort(...). Если нужен новый массив — это всегда map, что и отрабатывается в сегодняшних задачах на фильтрацию и группировку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: map/filter/reduce — декларативный стиль; sort всегда с compare-функцией для чисел.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Методы массивов

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Массив пользователей {name, age}: фильтр 18+, map в имена
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Сумма цен корзины через reduce
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Найди первый товар дороже 1000 через find
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь, все ли оценки ≥ 3 через every
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Отсортируй числа [10, 5, 40, 25] правильно: (a, b) => a - b
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Цепочка: фильтр активных задач → map в заголовки → join в строку
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Группировка задач по done через reduce
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Использованы map, filter, reduce в реальных задачах\n- [ ] Сортировка чисел корректна\n- [ ] Цепочка из 3+ методов в одной задаче

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Массив пользователей {name, age}: фильтр 18+, map в имена
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Сумма цен корзины через reduce
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Найди первый товар дороже 1000 через find
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь, все ли оценки ≥ 3 через every
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 05 day 6: array methods\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Мини-проект и закрепление

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Console Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Отладка — навык не менее важный, чем написание кода. Stack trace в Console показывает цепочку вызовов: читается снизу вверх — последний вызов (где упало) наверху. debugger в коде останавливает выполнение, если DevTools открыты — альтернатива ручному breakpoint в Sources.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Разбиение на функции (addTask, removeTask, listTasks) и файлы упрощает отладку: сломалось удаление — смотришь одну функцию, не весь скрипт. JSDoc (@param, @returns) документирует сигнатуру — IDE подсказывает типы до перехода на TypeScript.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Консольное Todo без DOM — чистая тренировка data layer: массив + функции. На неделе 6 тот же массив «оживят» через renderTasks().

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: отладка — это не «случайно наткнуться на исправление», а систематическое сужение области поиска, как игра в «горячо-холодно». Stack trace сразу указывает точное место падения и весь путь вызовов, которые к нему привели — это гораздо быстрее, чем расставлять console.log наугад по всему файлу и гадать, докуда код вообще дошёл.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: сегодняшний Console Task Manager без DOM — намеренно упрощённая версия завтрашнего (уже на неделе 6) реального приложения: тот же массив задач и те же функции addTask/removeTask останутся, просто добавится слой отрисовки renderTasks(). Умение отлаживать чистую логику отдельно от визуального слоя — ключевой навык: баг проще искать, когда переменных, которые могут быть виноваты, вдвое меньше.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: ошибка TypeError: Cannot read properties of undefined (reading 'title') в stack trace показывает точную строку и цепочку вызовов сверху вниз — читая её снизу вверх, видно: сначала вызвали listTasks(), та вызвала formatTask(task), и именно в formatTask task оказался undefined. Дальше остаётся понять, почему в массив попал пустой элемент — а не искать вслепую по всему файлу.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички читают текст ошибки только в первой строке и паникуют, не долистав до места в своём коде — часто первая строка указывает на встроенную функцию браузера, а причина в твоём коде находится на пару строк ниже в stack trace. Ещё одна ошибка новичков — удалять console.log сразу после того, как баг найден, вместо того чтобы оставить структурные логи или, ещё лучше, покрыть находку осмысленным именем переменной. Умение читать trace целиком, а не только заголовок, — то, что отрабатывается в сегодняшней практике с breakpoint.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: stack trace + breakpoint > десять console.log; функции — единицы отладки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Chrome DevTools: JavaScript

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Консольное приложение «Todo List» (массив + функции add/remove/list)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Поиск по задачам через filter
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Статистика: всего, выполнено, в процессе через reduce
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Отладь с breakpoint в DevTools Sources
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Напиши JSDoc для 3 ключевых функций
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь фильтр по статусу done / active
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Финальный коммит feat: todo manager core и тег week-05-done
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Todo list работает в Console без DOM\n- [ ] Код разбит на логические функции\n- [ ] Отладка через breakpoint, не только console.log

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Консольное приложение «Todo List» (массив + функции add/remove/list)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Поиск по задачам через filter
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Статистика: всего, выполнено, в процессе через reduce
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Отладь с breakpoint в DevTools Sources
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 05 day 7: console todo project\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Консольный менеджер задач — JS-приложение без DOM, управляемое из DevTools Console.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подробное описание: docs/projects.md — Неделя 5

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции: добавить задачу, удалить по id, отметить выполненной, фильтр по статусу, статистика.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] Массив объектов {id, title, done, createdAt}\n- [ ] Использованы map, filter, reduce, find\n- [ ] Минимум 8 функций, чистые где возможно\n- [ ] Код в репозитории с коммитом feat: todo manager core\n- [ ] CRUD полный: create, read, update (toggle done), delete\n- [ ] Фильтры: все / активные / выполненные\n- [ ] Статистика через reduce: всего, done, pending\n- [ ] Папка week-05/ с README и примером вызова функций в Console\n- [ ] Тег week-05-done на финальном коммите

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Разница let, const и почему не var?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что вернёт typeof NaN и как проверить NaN?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Разница map и forEach?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как отсортировать массив чисел по возрастанию?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Могу ли я написать FizzBuzz и объяснить каждую ветку?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Console Task Manager** в `learning-log/week-05/`, осмысленная Git-история, тег `week-05-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nJavaScript: типы, функции, массивы, чистый синтаксис\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-05-day-1", "label": "День 1 (Mon): Введение и переменные"}, {"id": "week-05-day-2", "label": "День 2 (Tue): Типы данных и операторы"}, {"id": "week-05-day-3", "label": "День 3 (Wed): Условия и циклы"}, {"id": "week-05-day-4", "label": "День 4 (Thu): Функции"}, {"id": "week-05-day-5", "label": "День 5 (Fri): Массивы — основы"}, {"id": "week-05-day-6", "label": "День 6 (Sat): Методы массивов"}, {"id": "week-05-day-7", "label": "День 7 (Sun): Мини-проект и закрепление"}, {"id": "week-05-project", "label": "Проект недели"}, {"id": "week-05-review", "label": "Ревью-чеклист"}], "text": "Неделя 5: JavaScript — переменные, типы, функции, массивы Цель недели: заложить фундамент JavaScript — синтаксис, типы данных, функции и работа с массивами. Литература: learn.javascript.ru , Kyle Simpson «You Don't Know JS» (Scope & Closures, Types & Grammar), MDN JavaScript Guide , JavaScript.info — углублённые объяснения, Eloquent JavaScript (гл. 1–4) Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-05/ День 1 (Mon): Введение и переменные Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Console Task Manager Теория JavaScript в браузере — язык, который оживляет страницу. Браузер парсит HTML, строит DOM, затем загружает и выполняе…"} \ No newline at end of file diff --git a/docs/weeks/06.json b/docs/weeks/06.json index 719441c..18f218c 100644 --- a/docs/weeks/06.json +++ b/docs/weeks/06.json @@ -1 +1 @@ -{"id": "week-06", "title": "DOM", "fullTitle": "Неделя 6: JavaScript — объекты, DOM, события", "html": "

                                                                                                                                                                                                                        Неделя 6: JavaScript — объекты, DOM, события

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: освоить объекты JavaScript, манипуляции DOM и обработку пользовательских событий.\nЛитература: learn.javascript.ru: Объекты, learn.javascript.ru: DOM, MDN DOM, DOM Enlightenment (архив) — глубокое понимание DOM, web.dev Learn Forms

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md\nGit: минимум 1 осмысленный коммит каждый день в learning-log/week-06/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Объекты — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DOM Todo App

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Объект в JavaScript — коллекция пар ключ–значение. Литерал { name: 'Анна', age: 25 } — самый частый способ создания. Доступ: точечная нотация user.name и скобочная user['name'] — вторая нужна для динамических ключей user[fieldName]. Методы — функции как свойства; внутри метода this ссылается на сам объект.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Объекты хранятся по ссылке: const b = a копирует ссылку, не содержимое. Shallow copy через {...obj} или Object.assign — вложенные объекты остаются общими. Object.keys, values, entries — обход свойств; entries удобен для рендеринга пар в DOM.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        for...in перебирает и унаследованные свойства — для собственных используй Object.keys или hasOwnProperty. Модель task = { id, title, done } с методом toggle() — мост к Todo App.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: объект — словарь по ссылке; spread копирует поверхностно, не глубоко.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Объекты — литералы, свойства, методы

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Объект user с полями name, email, age — чтение и изменение
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Метод user.greet() — function внутри объекта
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Перебери свойства через Object.entries и выведи пары ключ-значение
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Shallow copy: измени копию, убедись что вложенный объект общий
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Массив пользователей — 3+ объекта в массиве
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай объект task с {id, title, done} — модель для Todo
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь метод task.toggle() — переключает done
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Объект с минимум одним методом\n- [ ] Использованы keys/values/entries\n- [ ] Понимаю shallow vs deep copy (на уровне концепции)

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Объект user с полями name, email, age — чтение и изменение
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Метод user.greet() — function внутри объекта
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Перебери свойства через Object.entries и выведи пары ключ-значение
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Shallow copy: измени копию, убедись что вложенный объект общий
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 06 day 1: objects basics\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Деструктуризация и spread для объектов

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DOM Todo App

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Деструктуризация извлекает поля из объекта или элементы из массива в переменные: const { name, age } = user. Переименование: { name: userName }. Значения по умолчанию: { role = 'user' } — если поля нет. В параметрах функции printUser({ name, email }) сигнатура самодокументируется.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Spread в объектах объединяет и переопределяет: const config = { ...defaults, ...userConfig } — поля из userConfig побеждают. Порядок важен: правый объект перекрывает левый. Rest собирает остаток: const { id, ...rest } = productrest без id, удобно перед логированием без пароля.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Иммутабельное обновление: { ...task, done: true } — новый объект, оригинал не тронут. Паттерн для state management и React-подготовки. Swap переменных: [a, b] = [b, a] — элегантно через деструктуризацию массива.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: spread для merge и иммутабельного update; rest для «всё кроме».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Деструктурирующее присваивание

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Функция printUser({name, email, role = 'user'}) — деструктуризация параметров
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Объедини настройки: const config = {...defaults, ...userConfig}
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Исключи поле password из объекта перед логированием (rest)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Swap двух переменных через деструктуризацию массива [a, b] = [b, a]
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг Todo из недели 5 с деструктуризацией
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Иммутабельное обновление задачи: updateTask(tasks, id, {done: true})
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Деструктурируй массив: const [first, ...rest] = tasks
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Деструктуризация в параметрах функций\n- [ ] Spread для иммутабельного обновления объекта\n- [ ] Rest для исключения полей

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Функция printUser({name, email, role = 'user'}) — деструктуризация параметров
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Объедини настройки: const config = {...defaults, ...userConfig}
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Исключи поле password из объекта перед логированием (rest)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Swap двух переменных через деструктуризацию массива [a, b] = [b, a]
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 06 day 2: destructuring spread\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • for...in перебирает унаследованные свойства — используй hasOwnProperty или Object.keys
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Shallow copy не клонирует вложенные объекты
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Мутация объекта, переданного в функцию — ожидаемое поведение
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): DOM — поиск и изменение элементов

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DOM Todo App

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DOM (Document Object Model) — программный интерфейс к HTML-дереву. Браузер парсит разметку и строит дерево узлов; JavaScript может читать и изменять это дерево — текст обновляется на экране мгновенно. Поиск элементов: document.querySelector('.card') — первый; querySelectorAll — NodeList всех совпадений; getElementById — по id.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        textContent устанавливает текст и экранирует HTML — безопасно для пользовательского ввода. innerHTML парсит HTML-строку — XSS-уязвимость, если вставляешь данные пользователя. Создавай элементы через createElement, append, remove — чистый DOM API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        classList.add/remove/toggle/contains управляет классами без перезаписи всего className. dataset маппит data-*: el.dataset.pricedata-price. Кэшируй частые querySelector в объект elements — меньше обходов дерева.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: DOM — живое дерево; textContent для текста, createElement вместо innerHTML с user input.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: DOM-дерево\n- MDN DOM

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи JS к лендингу, выбери заголовок и измени textContent
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. По клику на кнопку меняй класс theme-dark на document.documentElement
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Динамически создай 5 элементов списка через createElement + append
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Удали элемент через remove()
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Читай data-атрибуты: data-price на карточках товаров
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай week-06/index.html — заготовка Todo App
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Вынеси DOM-ссылки в объект elements = { form, list, input }
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Используется querySelector, не устаревшие методы без причины\n- [ ] textContent для текста, не innerHTML с пользовательскими данными\n- [ ] Элементы создаются через DOM API, не строками HTML

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи JS к лендингу, выбери заголовок и измени textContent
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. По клику на кнопку меняй класс theme-dark на document.documentElement
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Динамически создай 5 элементов списка через createElement + append
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Удали элемент через remove()
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 06 day 3: dom manipulation\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): События — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DOM Todo App

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        События — способ браузера сообщить JS: «пользователь что-то сделал». addEventListener('click', handler) — современный стандарт; inline onclick в HTML — устарел и смешивает разметку с логикой. На один элемент можно повесить несколько обработчиков; onclick перезаписывает предыдущий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Объект события (event) несёт контекст: target — элемент, на котором сработало событие; currentTarget — элемент, на котором висит listener. preventDefault() отменяет действие браузера (submit формы, переход по ссылке), но не останавливает всплытие. stopPropagation() останавливает bubbling.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Всплытие (bubbling): клик по кнопке внутри li внутри ul сначала срабатывает на кнопке, затем всплывает к li, ul, body, document. Делегирование: один listener на ul ловит клики по всем li — эффективно для динамических списков. Для снятия обработчика нужна именованная функция — анонимную removeEventListener не найдёт.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: bubbling — основа делегирования; preventDefaultstopPropagation.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Введение в события

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Кнопка «Наверх» — плавный скролл (пока window.scrollTo, событие click)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Форма: submitpreventDefault(), вывод данных в Console
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Делегирование: один listener на ul, обработка кликов по li
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Клавиатура: keydown — закрытие модалки по Escape
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Удали listener через removeEventListener (именованная функция)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь stopPropagation на вложенной кнопке — наблюдай разницу
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Подключи { passive: true } на scroll listener (если добавишь)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] preventDefault на форме предотвращает перезагрузку\n- [ ] Event delegation на списке\n- [ ] Именованные handler-функции для removeEventListener

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Кнопка «Наверх» — плавный скролл (пока window.scrollTo, событие click)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Форма: submitpreventDefault(), вывод данных в Console
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Делегирование: один listener на ul, обработка кликов по li
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Клавиатура: keydown — закрытие модалки по Escape
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 06 day 4: events delegation\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Интерактивный UI

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DOM Todo App

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Интерактивный UI строится на переключении состояний: открыт/закрыт, активен/неактивен. Скрытие: атрибут hidden, класс .is-open, aria-hidden=\"true\" для скринридеров — лучше в комбинации. Таб-интерфейс: одна панель видима, остальные скрыты; активный таб помечается классом и aria-selected.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Модальное окно — фокус внутри диалога (focus trap): Tab не уходит за пределы. Закрытие по Escape, клику на overlay, кнопке «×». body { overflow: hidden } при открытой модалке блокирует скролл фона. event.target.closest('.card') поднимается от точки клика к ближайшему предку с классом — паттерн делегирования для карточек.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Аккордеон: aria-expanded на кнопке отражает состояние секции — обязательно для доступности. Всё это achievable без React — чистый DOM + классы + события.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: UI = состояние + DOM; ARIA синхронизирует визуал со скринридером.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Действия браузера

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Аккордеон: 3 секции, открыта одна; клик переключает
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Табы: панели контента показываются по активному табу
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Модалка «Подписаться» — открытие/закрытие, блокировка скролла body
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Счётчик лайков на карточках с делегированием
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Добавь aria-expanded на кнопки аккордеона
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Закрой модалку по клику на overlay и по Escape
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Переключи таб с клавиатуры (стрелки или Tab)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Аккордеон и табы работают без библиотек\n- [ ] Модалка закрывается по Escape и клику вне\n- [ ] ARIA-атрибуты на интерактивных элементах

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Аккордеон: 3 секции, открыта одна; клик переключает
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Табы: панели контента показываются по активному табу
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Модалка «Подписаться» — открытие/закрытие, блокировка скролла body
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Счётчик лайков на карточках с делегированием
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 06 day 5: accordion tabs modal\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Формы и валидация на JS

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DOM Todo App

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        HTML5-валидация — первый рубеж; JavaScript добавляет кастомную логику и UX. form.elements — коллекция полей формы; FormData собирает пары name–value; input.value, checkbox.checked — чтение состояния. Событие input срабатывает на каждый символ; change — при потере фокуса или выборе из select.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Constraint Validation API: field.validity (флаги ошибок), field.validationMessage, setCustomValidity('текст') — переопределяет сообщение браузера. form.checkValidity() — программная проверка перед submit. Показывай ошибки в <span class=\"error\"> под полем с aria-describedby — лучше одного alert().

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Disable кнопку submit, пока форма невалидна — предотвращает лишние попытки. HTML5 + JS вместе: нативные required/pattern + кастом «пароли совпадают» через setCustomValidity.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: input для live-валидации; ошибки у поля, не в alert; setCustomValidity для своих правил.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Формы, элементы управления

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Валидация формы регистрации перед отправкой
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Live-валидация email при input
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Пароли должны совпадать — setCustomValidity при несовпадении
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Вывод ошибок в <span class=\"error\"> под полями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. При успехе — сообщение «Регистрация успешна» без перезагрузки
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Свяжи ошибки с полями через aria-describedby
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Disable кнопку submit, пока форма невалидна
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] HTML5 + JS валидация работают вместе\n- [ ] Ошибки понятны и привязаны к полям\n- [ ] Форма не сабмитится при невалидных данных

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Валидация формы регистрации перед отправкой
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Live-валидация email при input
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Пароли должны совпадать — setCustomValidity при несовпадении
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Вывод ошибок в <span class=\"error\"> под полями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 06 day 6: form validation\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): DOM-проект — интерактивный лендинг

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DOM Todo App

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Зрелое DOM-приложение разделяет слои. Data layer — массив задач, чистые функции addTask, toggleTask; не знает о HTML. DOM layer — renderTasks(tasks), renderFilters(); читает data, обновляет дерево. App layer — связывает события с изменением data и вызовом render. Базовый MVC без фреймворка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DocumentFragment — контейнер в памяти: наполни список элементами, один append fragment — один reflow вместо N. Производительность: кэшируй DOM-ссылки; не читай offsetHeight и не пиши style вперемешку (layout thrashing). requestAnimationFrame — обзор для плавных анимаций чисел и скролла.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции render* — единая точка отрисовки: изменил data → вызвал renderTasks() → DOM синхронизирован. Todo App недели — CRUD через DOM, delegation на списке, фильтры, без innerHTML для user input.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: data отдельно от DOM; render* — мост; fragment — batch insert без лишних reflow.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: DocumentFragment

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Оживи лендинг: тёмная тема, мобильное меню, плавный скролл к секциям
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Фильтр портфолио: кнопки категорий скрывают/показывают карточки
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Счётчик «осталось мест» с анимацией числа
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Рефакторинг: вынеси DOM-операции в функции render*
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Протестируй весь UI с клавиатуры
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Собери Todo App: add, delete, toggle, filter — без innerHTML для input
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Финальный коммит и тег week-06-done
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Минимум 5 интерактивных фич\n- [ ] Код структурирован: utils, dom, app\n- [ ] Нет ошибок в Console при типичном сценарии

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Оживи лендинг: тёмная тема, мобильное меню, плавный скролл к секциям
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Фильтр портфолио: кнопки категорий скрывают/показывают карточки
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Счётчик «осталось мест» с анимацией числа
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Рефакторинг: вынеси DOM-операции в функции render*
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 06 day 7: dom todo app final\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Интерактивный Todo App — одностраничное приложение с DOM.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подробное описание: docs/projects.md — Неделя 6

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции: добавление, удаление, toggle done, фильтр (all/active/done), счётчик, localStorage (заготовка на след. неделю).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] CRUD задач через DOM, не innerHTML с user input\n- [ ] Event delegation на списке задач\n- [ ] Фильтры и счётчик активных\n- [ ] Доступность: labels, keyboard, aria на toggle\n- [ ] Папка week-06/ с README и скриншотом\n- [ ] Форма добавления с валидацией пустого ввода\n- [ ] Кнопка «Очистить выполненные» через filter + re-render\n- [ ] Код разделён: app.js, dom.js, tasks.js (или аналог)\n- [ ] Тег week-06-done на финальном коммите

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Разница textContent и innerHTML? Когда опасен innerHTML?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что такое event bubbling и зачем делегирование?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как предотвратить перезагрузку страницы при submit?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как скопировать объект без мутации оригинала (shallow)?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Могу ли я создать элемент и добавить его в DOM с нуля?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **DOM Todo App** в `learning-log/week-06/`, осмысленная Git-история, тег `week-06-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nDOM, события, интерактивный UI без фреймворков\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-06-day-1", "label": "День 1 (Mon): Объекты — основы"}, {"id": "week-06-day-2", "label": "День 2 (Tue): Деструктуризация и spread для объектов"}, {"id": "week-06-day-3", "label": "День 3 (Wed): DOM — поиск и изменение элементов"}, {"id": "week-06-day-4", "label": "День 4 (Thu): События — основы"}, {"id": "week-06-day-5", "label": "День 5 (Fri): Интерактивный UI"}, {"id": "week-06-day-6", "label": "День 6 (Sat): Формы и валидация на JS"}, {"id": "week-06-day-7", "label": "День 7 (Sun): DOM-проект — интерактивный лендинг"}, {"id": "week-06-project", "label": "Проект недели"}, {"id": "week-06-review", "label": "Ревью-чеклист"}], "text": "Неделя 6: JavaScript — объекты, DOM, события Цель недели: освоить объекты JavaScript, манипуляции DOM и обработку пользовательских событий. Литература: learn.javascript.ru: Объекты , learn.javascript.ru: DOM , MDN DOM , DOM Enlightenment (архив) — глубокое понимание DOM, web.dev Learn Forms Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-06/ День 1 (Mon): Объекты — основы Время (полный): ~50м теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~20м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к DOM Todo App Теория Объект в JavaScript — коллекция пар ключ–значение . Литерал { name: 'Анна', age: 25 } — самый частый способ создания. Доступ: точечная нотация user.name и скобочная user['name'] — вторая нужна для дин…"} \ No newline at end of file +{"id": "week-06", "title": "DOM", "fullTitle": "Неделя 6: JavaScript — объекты, DOM, события", "html": "

                                                                                                                                                                                                                        Неделя 6: JavaScript — объекты, DOM, события

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: освоить объекты JavaScript, манипуляции DOM и обработку пользовательских событий.\nЛитература: learn.javascript.ru: Объекты, learn.javascript.ru: DOM, MDN DOM, DOM Enlightenment (архив) — глубокое понимание DOM, web.dev Learn Forms

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md\nGit: минимум 1 осмысленный коммит каждый день в learning-log/week-06/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Объекты — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DOM Todo App

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Объект в JavaScript — коллекция пар ключ–значение. Литерал { name: 'Анна', age: 25 } — самый частый способ создания. Доступ: точечная нотация user.name и скобочная user['name'] — вторая нужна для динамических ключей user[fieldName]. Методы — функции как свойства; внутри метода this ссылается на сам объект.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Объекты хранятся по ссылке: const b = a копирует ссылку, не содержимое. Shallow copy через {...obj} или Object.assign — вложенные объекты остаются общими. Object.keys, values, entries — обход свойств; entries удобен для рендеринга пар в DOM.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        for...in перебирает и унаследованные свойства — для собственных используй Object.keys или hasOwnProperty. Модель task = { id, title, done } с методом toggle() — мост к Todo App.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: если массив — пронумерованный ряд ящиков, то объект — картотека с именованными карточками: чтобы найти нужное значение, не важен порядок, важно имя ключа. Хранение «по ссылке» удобно представить так: переменная — это не сам ящик с вещами, а бумажка с адресом ящика. Скопировав бумажку (const b = a), ты получаешь второй адрес того же самого ящика, а не новый ящик с копией содержимого.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: модель объекта {id, title, done} — это буквально структура данных, вокруг которой строится DOM Todo App на этой неделе и все последующие проекты курса. Понимание ссылочной природы объектов защитит от одного из самых частых источников багов в JS-приложениях — случайного изменения объекта, который используется сразу в нескольких местах программы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: const original = { count: 1 }; const copy = original; copy.count = 99; — после этого original.count тоже станет 99, потому что copy — не новый объект, а второй адрес того же самого. Чтобы получить независимую копию, нужен {...original} — но и он скопирует только верхний уровень: если внутри есть вложенный объект, он останется общим.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички думают, что const user = {} защищает объект от изменений, раз переменная константа. На деле const фиксирует только адрес (ссылку), а не содержимое — свойства объекта можно менять сколько угодно. Это стоит явно проверить в сегодняшней практике на шаге с shallow copy.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: объект — словарь по ссылке; spread копирует поверхностно, не глубоко.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Объекты — литералы, свойства, методы

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Объект user с полями name, email, age — чтение и изменение
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Метод user.greet() — function внутри объекта
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Перебери свойства через Object.entries и выведи пары ключ-значение
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Shallow copy: измени копию, убедись что вложенный объект общий
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Массив пользователей — 3+ объекта в массиве
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай объект task с {id, title, done} — модель для Todo
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь метод task.toggle() — переключает done
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Объект с минимум одним методом\n- [ ] Использованы keys/values/entries\n- [ ] Понимаю shallow vs deep copy (на уровне концепции)

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Объект user с полями name, email, age — чтение и изменение
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Метод user.greet() — function внутри объекта
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Перебери свойства через Object.entries и выведи пары ключ-значение
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Shallow copy: измени копию, убедись что вложенный объект общий
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 06 day 1: objects basics\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Деструктуризация и spread для объектов

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DOM Todo App

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Деструктуризация извлекает поля из объекта или элементы из массива в переменные: const { name, age } = user. Переименование: { name: userName }. Значения по умолчанию: { role = 'user' } — если поля нет. В параметрах функции printUser({ name, email }) сигнатура самодокументируется.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Spread в объектах объединяет и переопределяет: const config = { ...defaults, ...userConfig } — поля из userConfig побеждают. Порядок важен: правый объект перекрывает левый. Rest собирает остаток: const { id, ...rest } = productrest без id, удобно перед логированием без пароля.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Иммутабельное обновление: { ...task, done: true } — новый объект, оригинал не тронут. Паттерн для state management и React-подготовки. Swap переменных: [a, b] = [b, a] — элегантно через деструктуризацию массива.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: деструктуризация — это распаковка посылки: вместо того чтобы работать с целым объектом (user.name, user.age в трёх разных местах), ты сразу «раскладываешь» нужные поля по отдельным переменным, а посылку (сам объект) можно выбросить. Spread, наоборот, — упаковка: собираешь несколько маленьких объектов в один новый, причём поля справа перекрывают поля слева, как более поздняя запись в анкете перебивает раннюю.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: иммутабельное обновление через spread ({...task, done: true}) — это ровно тот паттерн, который лежит в основе state management в React и других фреймворках: там объекты никогда не мутируют напрямую, только заменяются новыми копиями с изменённым полем. Освоив это сейчас на простых задачах, ты избежишь одной из самых частых путаниц при переходе на фреймворки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: обновление задачи в списке без мутации — tasks.map(t => t.id === id ? {...t, done: true} : t): создаётся новый массив, где нужный элемент заменён на новый объект с изменённым полем, а все остальные элементы остаются теми же ссылками. Так реактивные системы могут быстро понять, что именно изменилось, сравнивая ссылки, а не обходя все поля.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички считают, что порядок spread не важен — «ведь мы просто объединяем объекты». На деле {...defaults, ...userConfig} и {...userConfig, ...defaults} дадут разные результаты: во втором случае defaults перезапишет пользовательские настройки, что обычно не то, что нужно. Порядок «от общего к частному» стоит проверить в сегодняшней задаче на merge конфигураций.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: spread для merge и иммутабельного update; rest для «всё кроме».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Деструктурирующее присваивание

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Функция printUser({name, email, role = 'user'}) — деструктуризация параметров
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Объедини настройки: const config = {...defaults, ...userConfig}
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Исключи поле password из объекта перед логированием (rest)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Swap двух переменных через деструктуризацию массива [a, b] = [b, a]
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг Todo из недели 5 с деструктуризацией
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Иммутабельное обновление задачи: updateTask(tasks, id, {done: true})
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Деструктурируй массив: const [first, ...rest] = tasks
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Деструктуризация в параметрах функций\n- [ ] Spread для иммутабельного обновления объекта\n- [ ] Rest для исключения полей

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Функция printUser({name, email, role = 'user'}) — деструктуризация параметров
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Объедини настройки: const config = {...defaults, ...userConfig}
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Исключи поле password из объекта перед логированием (rest)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Swap двух переменных через деструктуризацию массива [a, b] = [b, a]
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 06 day 2: destructuring spread\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • for...in перебирает унаследованные свойства — используй hasOwnProperty или Object.keys
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Shallow copy не клонирует вложенные объекты
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Мутация объекта, переданного в функцию — ожидаемое поведение
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): DOM — поиск и изменение элементов

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DOM Todo App

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DOM (Document Object Model) — программный интерфейс к HTML-дереву. Браузер парсит разметку и строит дерево узлов; JavaScript может читать и изменять это дерево — текст обновляется на экране мгновенно. Поиск элементов: document.querySelector('.card') — первый; querySelectorAll — NodeList всех совпадений; getElementById — по id.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        textContent устанавливает текст и экранирует HTML — безопасно для пользовательского ввода. innerHTML парсит HTML-строку — XSS-уязвимость, если вставляешь данные пользователя. Создавай элементы через createElement, append, remove — чистый DOM API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        classList.add/remove/toggle/contains управляет классами без перезаписи всего className. dataset маппит data-*: el.dataset.pricedata-price. Кэшируй частые querySelector в объект elements — меньше обходов дерева.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: до сих пор JS был отдельно от страницы — вычислял что-то в Console, не трогая экран. DOM API — это мост между кодом и тем, что видит пользователь: HTML создаёт начальное дерево, а дальше JS может строить, изменять и удалять узлы этого дерева точно так же, как строил бы данные в объекте или массиве. Разница в том, что каждое изменение дерева браузер сразу же перерисовывает на экране.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: сегодняшний навык — основа для всей недели и всего DOM Todo App: добавление задачи в интерфейсе — это буквально createElement + append; удаление — remove(). Без уверенного владения поиском и изменением элементов невозможно перейти к событиям (завтра) и интерактивному UI (позже на неделе).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: вывод пользовательского имени на страницу через card.innerHTML = userName кажется удобным, но если userName содержит <img src=x onerror=\"alert(1)\">, браузер выполнит этот код как разметку — классическая XSS-атака. card.textContent = userName в той же ситуации просто покажет текст как есть, безопасно экранировав спецсимволы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички считают innerHTML универсальным способом «вставить что угодно», не задумываясь об источнике данных. Правило простое: innerHTML допустим только для доверенной, статичной разметки (например, шаблона из твоего же кода), а любые данные, пришедшие от пользователя или внешнего API, должны идти через textContent или createElement — это и отрабатывается в сегодняшней практике на карточках товаров. Ещё одна ловушка — частые обращения к querySelector внутри циклов или обработчиков: каждый вызов заново обходит дерево DOM, поэтому ссылки на часто используемые элементы стоит один раз сохранить в объекте и переиспользовать.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: DOM — живое дерево; textContent для текста, createElement вместо innerHTML с user input.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: DOM-дерево\n- MDN DOM

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи JS к лендингу, выбери заголовок и измени textContent
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. По клику на кнопку меняй класс theme-dark на document.documentElement
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Динамически создай 5 элементов списка через createElement + append
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Удали элемент через remove()
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Читай data-атрибуты: data-price на карточках товаров
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай week-06/index.html — заготовка Todo App
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Вынеси DOM-ссылки в объект elements = { form, list, input }
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Используется querySelector, не устаревшие методы без причины\n- [ ] textContent для текста, не innerHTML с пользовательскими данными\n- [ ] Элементы создаются через DOM API, не строками HTML

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи JS к лендингу, выбери заголовок и измени textContent
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. По клику на кнопку меняй класс theme-dark на document.documentElement
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Динамически создай 5 элементов списка через createElement + append
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Удали элемент через remove()
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 06 day 3: dom manipulation\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): События — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DOM Todo App

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        События — способ браузера сообщить JS: «пользователь что-то сделал». addEventListener('click', handler) — современный стандарт; inline onclick в HTML — устарел и смешивает разметку с логикой. На один элемент можно повесить несколько обработчиков; onclick перезаписывает предыдущий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Объект события (event) несёт контекст: target — элемент, на котором сработало событие; currentTarget — элемент, на котором висит listener. preventDefault() отменяет действие браузера (submit формы, переход по ссылке), но не останавливает всплытие. stopPropagation() останавливает bubbling.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Всплытие (bubbling): клик по кнопке внутри li внутри ul сначала срабатывает на кнопке, затем всплывает к li, ul, body, document. Делегирование: один listener на ul ловит клики по всем li — эффективно для динамических списков. Для снятия обработчика нужна именованная функция — анонимную removeEventListener не найдёт.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: представь всплытие как круги на воде: бросаешь камень (клик) в конкретную точку (элемент), а волна расходится наружу через всех родителей до самого document. Делегирование пользуется этим эффектом: вместо того чтобы ставить сторожа (listener) у каждого маленького элемента, ты ставишь одного сторожа на общий контейнер — он «слышит» волну от любого клика внутри и по event.target понимает, где именно она началась.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: делегирование — обязательный приём для динамических списков (Todo App этой недели, где задачи добавляются и удаляются во время работы страницы). Если вешать listener на каждый элемент списка отдельно, новые элементы, добавленные позже, окажутся без обработчика — типичный источник бага «кнопка удаления не работает у новых задач».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: список задач с одним обработчиком на ul: list.addEventListener('click', e => { if (e.target.matches('.delete-btn')) removeTask(e.target.closest('li').dataset.id) }). Этот код продолжит работать для любой новой задачи, добавленной позже, потому что слушатель висит не на кнопках, а на их общем родителе.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички думают, что preventDefault() останавливает и всплытие события — но это не так, эти два механизма независимы. preventDefault() отменяет действие браузера по умолчанию (переход по ссылке, отправку формы), а stopPropagation() останавливает распространение события вверх по дереву. Спутав их, легко получить форму, которая не перезагружает страницу, но клик по ней всё равно «протекает» на родительские обработчики — это стоит явно проверить в сегодняшней задаче с stopPropagation.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: bubbling — основа делегирования; preventDefaultstopPropagation.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Введение в события

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Кнопка «Наверх» — плавный скролл (пока window.scrollTo, событие click)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Форма: submitpreventDefault(), вывод данных в Console
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Делегирование: один listener на ul, обработка кликов по li
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Клавиатура: keydown — закрытие модалки по Escape
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Удали listener через removeEventListener (именованная функция)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь stopPropagation на вложенной кнопке — наблюдай разницу
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Подключи { passive: true } на scroll listener (если добавишь)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] preventDefault на форме предотвращает перезагрузку\n- [ ] Event delegation на списке\n- [ ] Именованные handler-функции для removeEventListener

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Кнопка «Наверх» — плавный скролл (пока window.scrollTo, событие click)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Форма: submitpreventDefault(), вывод данных в Console
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Делегирование: один listener на ul, обработка кликов по li
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Клавиатура: keydown — закрытие модалки по Escape
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 06 day 4: events delegation\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Интерактивный UI

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DOM Todo App

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Интерактивный UI строится на переключении состояний: открыт/закрыт, активен/неактивен. Скрытие: атрибут hidden, класс .is-open, aria-hidden=\"true\" для скринридеров — лучше в комбинации. Таб-интерфейс: одна панель видима, остальные скрыты; активный таб помечается классом и aria-selected.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Модальное окно — фокус внутри диалога (focus trap): Tab не уходит за пределы. Закрытие по Escape, клику на overlay, кнопке «×». body { overflow: hidden } при открытой модалке блокирует скролл фона. event.target.closest('.card') поднимается от точки клика к ближайшему предку с классом — паттерн делегирования для карточек.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Аккордеон: aria-expanded на кнопке отражает состояние секции — обязательно для доступности. Всё это achievable без React — чистый DOM + классы + события.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: любой интерактивный UI-компонент можно описать как автомат с конечным числом состояний: модалка «открыта» или «закрыта», таб «активен» или нет. Задача JS — не «рисовать» интерфейс заново каждый раз, а переключать состояние (обычно через класс или атрибут) и позволить CSS решить, как это состояние выглядит визуально. DOM в этой модели — просто зеркало текущего состояния, а не источник истины.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: ровно этот подход — «состояние определяет вид» — лежит в основе React и других современных фреймворков, только там переключение состояния автоматически вызывает перерисовку. Отрабатывая аккордеон и табы на чистом JS сейчас, ты позже быстрее поймёшь, зачем вообще нужен фреймворк поверх этой идеи.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: аккордеон без библиотек: клик по заголовку переключает класс .is-open у секции и aria-expanded у кнопки одновременно — section.classList.toggle('is-open'); button.setAttribute('aria-expanded', isOpen). CSS через .is-open { max-height: ... } показывает содержимое — JS не занимается анимацией напрямую, только состоянием.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички считают доступность (ARIA) «опциональной красотой для галочки». На деле aria-expanded/aria-hidden — это единственный способ, которым скринридер узнаёт о состоянии визуального компонента: без них пользователь с экранным диктором не поймёт, открыта секция или нет, даже если зрячему пользователю всё очевидно по анимации. Похожая ошибка — закрывать модалку только по клику на «×», забывая про Escape и клик по overlay: пользователь, привыкший к стандартному поведению модалок, будет считать интерфейс сломанным. Это стоит закрепить в сегодняшней практике на аккордеоне и модалке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: UI = состояние + DOM; ARIA синхронизирует визуал со скринридером.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Действия браузера

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Аккордеон: 3 секции, открыта одна; клик переключает
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Табы: панели контента показываются по активному табу
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Модалка «Подписаться» — открытие/закрытие, блокировка скролла body
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Счётчик лайков на карточках с делегированием
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Добавь aria-expanded на кнопки аккордеона
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Закрой модалку по клику на overlay и по Escape
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Переключи таб с клавиатуры (стрелки или Tab)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Аккордеон и табы работают без библиотек\n- [ ] Модалка закрывается по Escape и клику вне\n- [ ] ARIA-атрибуты на интерактивных элементах

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Аккордеон: 3 секции, открыта одна; клик переключает
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Табы: панели контента показываются по активному табу
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Модалка «Подписаться» — открытие/закрытие, блокировка скролла body
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Счётчик лайков на карточках с делегированием
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 06 day 5: accordion tabs modal\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Формы и валидация на JS

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DOM Todo App

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        HTML5-валидация — первый рубеж; JavaScript добавляет кастомную логику и UX. form.elements — коллекция полей формы; FormData собирает пары name–value; input.value, checkbox.checked — чтение состояния. Событие input срабатывает на каждый символ; change — при потере фокуса или выборе из select.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Constraint Validation API: field.validity (флаги ошибок), field.validationMessage, setCustomValidity('текст') — переопределяет сообщение браузера. form.checkValidity() — программная проверка перед submit. Показывай ошибки в <span class=\"error\"> под полем с aria-describedby — лучше одного alert().

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Disable кнопку submit, пока форма невалидна — предотвращает лишние попытки. HTML5 + JS вместе: нативные required/pattern + кастом «пароли совпадают» через setCustomValidity.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: валидацию удобно представлять как два рубежа обороны. Первый — HTML5-атрибуты (required, pattern, type=\"email\") — быстрый и бесплатный, браузер сам показывает стандартное сообщение. Второй — JS-логика для правил, которые HTML5 не умеет выразить (совпадение паролей, проверка на сервере, кастомные форматы) — здесь ты сам решаешь, когда показать ошибку и как её сформулировать.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: формы — точка входа пользовательских данных в любое приложение, и на неделе 7 та же форма отправит данные через fetch на сервер. Уже сейчас важно приучиться не доверять вводу вслепую: проверка на клиенте улучшает UX (мгновенная обратная связь), но не заменяет проверку на сервере — клиентский JS всегда можно отключить или обойти.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: живая проверка email при каждом вводе символа — emailInput.addEventListener('input', () => { errorSpan.textContent = emailInput.validity.valid ? '' : 'Введите корректный email' }). Пользователь видит ошибку сразу после того, как начал печатать неправильный адрес, а не только после попытки отправить форму.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички показывают ошибки валидации через alert(), что прерывает работу пользователя навязчивым модальным окном и не указывает конкретное проблемное поле. Правильный паттерн — вывод текста ошибки рядом с полем через <span class=\"error\">, связанный с input через aria-describedby — так ошибка видна в контексте и доступна для скринридеров. Ещё одна частая недоработка — валидировать только при submit, из-за чего пользователь узнаёт об ошибке в пароле лишь после заполнения всей формы; событие input решает это, показывая проблему сразу. Это — основа сегодняшней практики.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: input для live-валидации; ошибки у поля, не в alert; setCustomValidity для своих правил.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Формы, элементы управления

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Валидация формы регистрации перед отправкой
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Live-валидация email при input
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Пароли должны совпадать — setCustomValidity при несовпадении
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Вывод ошибок в <span class=\"error\"> под полями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. При успехе — сообщение «Регистрация успешна» без перезагрузки
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Свяжи ошибки с полями через aria-describedby
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Disable кнопку submit, пока форма невалидна
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] HTML5 + JS валидация работают вместе\n- [ ] Ошибки понятны и привязаны к полям\n- [ ] Форма не сабмитится при невалидных данных

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Валидация формы регистрации перед отправкой
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Live-валидация email при input
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Пароли должны совпадать — setCustomValidity при несовпадении
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Вывод ошибок в <span class=\"error\"> под полями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 06 day 6: form validation\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): DOM-проект — интерактивный лендинг

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DOM Todo App

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Зрелое DOM-приложение разделяет слои. Data layer — массив задач, чистые функции addTask, toggleTask; не знает о HTML. DOM layer — renderTasks(tasks), renderFilters(); читает data, обновляет дерево. App layer — связывает события с изменением data и вызовом render. Базовый MVC без фреймворка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DocumentFragment — контейнер в памяти: наполни список элементами, один append fragment — один reflow вместо N. Производительность: кэшируй DOM-ссылки; не читай offsetHeight и не пиши style вперемешку (layout thrashing). requestAnimationFrame — обзор для плавных анимаций чисел и скролла.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции render* — единая точка отрисовки: изменил data → вызвал renderTasks() → DOM синхронизирован. Todo App недели — CRUD через DOM, delegation на списке, фильтры, без innerHTML для user input.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: разделение на data layer и DOM layer — это разделение «что происходит» и «как это выглядит». Данные (массив задач) — источник истины, независимый от экрана; DOM — просто их визуальное отражение в конкретный момент. Каждое изменение проходит по циклу: меняем данные → вызываем один и тот же render* → DOM обновляется целиком по актуальным данным, а не точечными правками в разных местах кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: этот цикл «данные → render → DOM» — упрощённая версия того, как работает React и другие декларативные фреймворки: там ты тоже описываешь UI как функцию от состояния, а библиотека сама решает, что обновить на экране. Освоив паттерн вручную сейчас, ты поймёшь, зачем вообще нужен React, когда дойдёшь до него.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: без разделения слоёв удаление задачи выглядело бы как ручной поиск нужного <li> в DOM и его удаление в нескольких разных обработчиках. С разделением: removeTask(id) меняет только массив данных, а единственный вызов renderTasks() перерисовывает список целиком — на 50 задач и на 5000 логика одна и та же, разница только в производительности, которую решает DocumentFragment.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички считают частые обращения к innerHTML для вставки списка «более простым» способом, чем render* с DOM API — код действительно короче, но при user input (например, названии задачи) это открывает XSS, а также требует полной пересборки строки при каждом малейшем изменении. Итоговый Todo App должен использовать createElement/append внутри renderTasks(), что и проверяют критерии сегодняшней практики.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: data отдельно от DOM; render* — мост; fragment — batch insert без лишних reflow.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: DocumentFragment

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Оживи лендинг: тёмная тема, мобильное меню, плавный скролл к секциям
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Фильтр портфолио: кнопки категорий скрывают/показывают карточки
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Счётчик «осталось мест» с анимацией числа
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Рефакторинг: вынеси DOM-операции в функции render*
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Протестируй весь UI с клавиатуры
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Собери Todo App: add, delete, toggle, filter — без innerHTML для input
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Финальный коммит и тег week-06-done
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Минимум 5 интерактивных фич\n- [ ] Код структурирован: utils, dom, app\n- [ ] Нет ошибок в Console при типичном сценарии

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Оживи лендинг: тёмная тема, мобильное меню, плавный скролл к секциям
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Фильтр портфолио: кнопки категорий скрывают/показывают карточки
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Счётчик «осталось мест» с анимацией числа
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Рефакторинг: вынеси DOM-операции в функции render*
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 06 day 7: dom todo app final\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Интерактивный Todo App — одностраничное приложение с DOM.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подробное описание: docs/projects.md — Неделя 6

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции: добавление, удаление, toggle done, фильтр (all/active/done), счётчик, localStorage (заготовка на след. неделю).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] CRUD задач через DOM, не innerHTML с user input\n- [ ] Event delegation на списке задач\n- [ ] Фильтры и счётчик активных\n- [ ] Доступность: labels, keyboard, aria на toggle\n- [ ] Папка week-06/ с README и скриншотом\n- [ ] Форма добавления с валидацией пустого ввода\n- [ ] Кнопка «Очистить выполненные» через filter + re-render\n- [ ] Код разделён: app.js, dom.js, tasks.js (или аналог)\n- [ ] Тег week-06-done на финальном коммите

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Разница textContent и innerHTML? Когда опасен innerHTML?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что такое event bubbling и зачем делегирование?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как предотвратить перезагрузку страницы при submit?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как скопировать объект без мутации оригинала (shallow)?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Могу ли я создать элемент и добавить его в DOM с нуля?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **DOM Todo App** в `learning-log/week-06/`, осмысленная Git-история, тег `week-06-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nDOM, события, интерактивный UI без фреймворков\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-06-day-1", "label": "День 1 (Mon): Объекты — основы"}, {"id": "week-06-day-2", "label": "День 2 (Tue): Деструктуризация и spread для объектов"}, {"id": "week-06-day-3", "label": "День 3 (Wed): DOM — поиск и изменение элементов"}, {"id": "week-06-day-4", "label": "День 4 (Thu): События — основы"}, {"id": "week-06-day-5", "label": "День 5 (Fri): Интерактивный UI"}, {"id": "week-06-day-6", "label": "День 6 (Sat): Формы и валидация на JS"}, {"id": "week-06-day-7", "label": "День 7 (Sun): DOM-проект — интерактивный лендинг"}, {"id": "week-06-project", "label": "Проект недели"}, {"id": "week-06-review", "label": "Ревью-чеклист"}], "text": "Неделя 6: JavaScript — объекты, DOM, события Цель недели: освоить объекты JavaScript, манипуляции DOM и обработку пользовательских событий. Литература: learn.javascript.ru: Объекты , learn.javascript.ru: DOM , MDN DOM , DOM Enlightenment (архив) — глубокое понимание DOM, web.dev Learn Forms Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-06/ День 1 (Mon): Объекты — основы Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~45м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к DOM Todo App Теория Объект в JavaScript — коллекция пар ключ–значение . Литерал { name: 'Анна', age: 25 } — самый частый способ создания. Доступ: точечная нотация user.name и скобочная user['name'] — вторая нужна для дина…"} \ No newline at end of file diff --git a/docs/weeks/07.json b/docs/weeks/07.json index 77db0a6..cbc4c11 100644 --- a/docs/weeks/07.json +++ b/docs/weeks/07.json @@ -1 +1 @@ -{"id": "week-07", "title": "Modules & API", "fullTitle": "Неделя 7: JavaScript — localStorage, Fetch, формы, модули ES", "html": "

                                                                                                                                                                                                                        Неделя 7: JavaScript — localStorage, Fetch, формы, модули ES

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: научиться сохранять данные в браузере, работать с API и организовывать код в ES-модули.\nЛитература: learn.javascript.ru: Fetch, MDN Web Storage, MDN JavaScript modules, JSONPlaceholder Guide, web.dev Storage for the web

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md\nGit: минимум 1 осмысленный коммит каждый день в learning-log/week-07/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): localStorage и sessionStorage

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~35м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Notes Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Web Storage API даёт браузеру простое key-value хранилище, привязанное к origin (протокол + домен + порт). localStorage и sessionStorage работают одинаково по API, но различаются временем жизни: localStorage сохраняет данные между сессиями, а sessionStorage очищается при закрытии вкладки. Оба интерфейса принимают только строки — если нужно сохранить объект или массив, сначала сериализуй его через JSON.stringify, а при чтении восстанови через JSON.parse.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Основные методы: setItem(key, value), getItem(key) (возвращает null, если ключа нет), removeItem(key) и clear(). API синхронный: каждая операция выполняется на main thread, поэтому не стоит записывать большие объёмы данных за раз. Типичный лимит — около 5 МБ на origin; при переполнении браузер выбросит QuotaExceededError.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для настроек UI (тема, язык, черновики форм) localStorage — естественный выбор. Но это не защищённое хранилище: любой JavaScript на странице (в том числе внедрённый через XSS) может прочитать все ключи. Пароли, JWT и API-ключи в localStorage хранить нельзя. Пользователь или расширение браузера могут вручную изменить значение в DevTools — поэтому JSON.parse всегда оборачивай в try/catch и задавай разумные значения по умолчанию при ошибке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Window.localStorage\n- MDN: Web Storage API\n- web.dev: Storage for the web

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: localStorage — удобный кэш для UI-состояния, но не сейф для секретов и не замена серверной базе данных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сохрани Todo-список в localStorage при каждом изменении
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. При загрузке страницы восстанови задачи из storage
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Кнопка «Очистить всё» — removeItem + обновление UI
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сохрани тему оформления (light/dark) между сессиями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Обработай случай битого JSON в getItem (try/catch)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай ключ week-07-notes — заготовка для проекта недели
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Вынеси работу со storage в функции saveState / loadState
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Данные переживают перезагрузку страницы\n- [ ] Объекты сериализуются через JSON\n- [ ] Ошибки парсинга обработаны gracefully

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сохрани Todo-список в localStorage при каждом изменении
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. При загрузке страницы восстанови задачи из storage
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Кнопка «Очистить всё» — removeItem + обновление UI
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сохрани тему оформления (light/dark) между сессиями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 07 day 1: localStorage persist\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Хранение паролей и токенов в localStorage — уязвимость XSS
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Забытый JSON.parse — строка \"[object Object]\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • QuotaExceededError при переполнении — редко, но возможно
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): JSON и работа с данными

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~35м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Notes Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        JSON (JavaScript Object Notation) — текстовый формат обмена данными между клиентом, сервером и файлами. Он поддерживает объекты, массивы, строки, числа, true/false и null, но не функции, undefined и комментарии. При JSON.stringify объекты Date превращаются в ISO-строки, а undefined в свойствах объекта просто опускаются — это важно помнить при экспорте данных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Метод JSON.stringify(obj, replacer, space) умеет фильтровать поля (через массив ключей или функцию-replacer) и форматировать вывод: space: 2 делает JSON читаемым для человека при отладке. Обратная операция — JSON.parse, которая бросает SyntaxError на невалидном тексте. Импорт из файла всегда требует валидации: проверь наличие обязательных полей, типы и допустимые значения до того, как смешаешь чужие данные со своим состоянием.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        В приложениях с localStorage данные со временем меняют форму. Добавь поле schemaVersion в сохраняемый объект — при загрузке сравни версию и при необходимости мигрируй старый формат в новый. Обновления списков объектов делай иммутабельно: items.map(item => item.id === id ? { ...item, title } : item) вместо прямой мутации элемента массива. Так проще отслеживать изменения и избегать побочных эффектов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Working with JSON\n- MDN: JSON.stringify()\n- learn.javascript.ru: Формат JSON

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: JSON — контракт обмена данными; валидация и версионирование схемы защищают приложение от битых импортов и устаревших сохранений.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Экспорт Todo в JSON-файл (download через Blob + URL.createObjectURL)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Импорт: <input type=\"file\"> → FileReader → parse → merge в список
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Функция validateTodo(data) — проверка обязательных полей
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Статистика: группировка задач по дате создания
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Миграция данных: если версия схемы старая — обнови формат
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь exportedAt в экспортируемый JSON
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Отклони импорт с понятным сообщением при невалидном файле
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Экспорт/импорт JSON работает\n- [ ] Валидация отклоняет невалидные данные\n- [ ] Иммутабельные обновления, не мутация массива напрямую

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Экспорт Todo в JSON-файл (download через Blob + URL.createObjectURL)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Импорт: <input type=\"file\"> → FileReader → parse → merge в список
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Функция validateTodo(data) — проверка обязательных полей
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Статистика: группировка задач по дате создания
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 07 day 2: json import export\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): Fetch API — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Notes Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Fetch API — современный способ делать HTTP-запросы из браузера. Вызов fetch(url) сразу возвращает Promise, который разрешается объектом Response, ещё до того как тело ответа полностью загружено. Чтобы получить JSON, нужна вторая асинхронная операция: response.json(), которая тоже возвращает Promise. Типичная цепочка: fetch(url).then(r => r.json()).then(data => ...).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Важная особенность: fetch не отклоняет Promise при HTTP-ошибках вроде 404 или 500. Promise reject происходит только при сетевых сбоях (нет интернета, CORS, таймаут DNS). Поэтому всегда проверяй response.ok (это shorthand для статусов 200–299) и обрабатывай неуспешные ответы явно — выброси ошибку или верни понятное сообщение пользователю.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для POST-запросов передай объект опций вторым аргументом: method: 'POST', headers: { 'Content-Type': 'application/json' } и body: JSON.stringify(data). Без правильного Content-Type сервер может не распознать тело как JSON. Для обучения удобен JSONPlaceholder — бесплатный mock REST API без регистрации, имитирующий посты, пользователей и комментарии.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Fetch\n- MDN: Using Fetch\n- JSONPlaceholder Guide

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: fetch различает «сеть упала» (reject) и «сервер ответил ошибкой» (resolve с ok: false) — проверяй оба случая.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Загрузи посты с JSONPlaceholder
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Отобрази список заголовков в DOM
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Обработай loading state (текст «Загрузка...») и error state
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. POST новый пост на API, выведи ответ в Console
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Используй async/await (предпросмотр, углубление на неделе 8)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай функцию fetchJson(url) с проверкой response.ok
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Покажи empty state, если массив постов пуст
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Данные с API отображаются в UI\n- [ ] Обработаны loading и error\n- [ ] Проверяется response.ok

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Загрузи посты с JSONPlaceholder
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Отобрази список заголовков в DOM
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Обработай loading state (текст «Загрузка...») и error state
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. POST новый пост на API, выведи ответ в Console
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 07 day 3: fetch api basics\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): Работа с публичными API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~35м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Notes Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Публичные REST API организуют данные вокруг ресурсов — сущностей вроде «пользователь», «пост» или «город». URL описывает что запрашиваешь (/users/42), а HTTP-метод — какое действие выполняешь (GET — прочитать, POST — создать). Ответ сервера сопровождается статус-кодом: 200 — успех, 201 — создано, 400 — ошибка клиента, 404 — не найдено, 500 — ошибка сервера. Умение читать статус и тело ответа — базовый навык интеграции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Параметры запроса передаются в query string: ?q=moscow&page=2. Спецсимволы и пробелы кодируй через URLSearchParams, а не вручную — иначе поиск по «New York» сломается. Перед интеграцией изучи документацию API: какие endpoints доступны, какие поля обязательны, есть ли лимиты на количество запросов (rate limiting). OpenAPI/Swagger-спецификация — стандартный формат, где всё это описано машиночитаемо.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CORS (Cross-Origin Resource Sharing) — механизм безопасности браузера. Если твой сайт на localhost:5500, а API на другом домене, браузер спросит сервер: «разрешён ли этот origin?». Если сервер не вернёт нужные заголовки (Access-Control-Allow-Origin), fetch заблокируется — это не баг твоего кода, а политика браузера. API-ключи в production-коде на клиенте видны всем — для секретных ключей нужен backend-прокси.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: CORS\n- MDN: HTTP Overview\n- Open-Meteo API

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: интеграция с API начинается с чтения документации и понимания HTTP-семантики, а не с написания fetch.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Погода: Open-Meteo API — без ключа
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Форма поиска города → fetch → отображение температуры и иконки
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Пагинация: загрузи страницы постов JSONPlaceholder по кнопке «Ещё»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Обработай 404 и сетевую ошибку разными сообщениями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Дебаг запросов в DevTools → Network
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. GitHub Users API: поиск по логину — заготовка для проекта
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Документируй используемые endpoints в комментарии api.js
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Реальный API интегрирован в UI\n- [ ] Пользователь видит понятные сообщения об ошибках\n- [ ] Network panel использован для отладки

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Погода: Open-Meteo API — без ключа
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Форма поиска города → fetch → отображение температуры и иконки
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Пагинация: загрузи страницы постов JSONPlaceholder по кнопке «Ещё»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Обработай 404 и сетевую ошибку разными сообщениями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 07 day 4: public apis weather github\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): ES-модули

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Notes Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        ES-модули — стандартный способ организации JavaScript-кода в файлах с явными зависимостями. Каждый файл — отдельный модуль со своей областью видимости: переменные не попадают в глобальный window. Чтобы сделать функцию или константу доступной снаружи, используй export. Импорт: import { fetchPosts } from './api.js' для именованного экспорта или import render from './render.js' для default.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        В HTML подключай модули через <script type=\"module\" src=\"main.js\">. Такой скрипт выполняется в strict mode, откладывается (defer) и загружается как модуль — браузер сам разрешит дерево зависимостей. В пути импорта обязательно указывай расширение .js — в отличие от bundler-ов, нативные модули в браузере этого требуют. Открытие файла через file:// не сработает из-за CORS; нужен локальный HTTP-сервер (Live Server, npx serve).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Именованный export предпочтителен, когда из файла экспортируется несколько сущностей — имена явные при импорте и рефакторинге. Default export удобен для «главной» сущности файла (один компонент, один класс). Типичная структура проекта: api/ — запросы, ui/ — рендер DOM, utils/ — хелперы, main.js — точка входа, которая только связывает модули.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Модули\n- MDN: JavaScript modules\n- javascript.info: Модули

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: модули превращают монолитный скрипт в граф зависимостей с изолированными областями видимости — основа масштабируемого фронтенда.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Разбей Todo App на модули: storage.js, todo.js, render.js, main.js
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. api.js — функции fetch с экспортом
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Переименование при импорте: import { fetchPosts as getPosts }
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Запуск через Live Server (модули требуют HTTP, не file://)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Циклические зависимости — избегай, рефакторинг при необходимости
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай week-07/js/ с 5+ модулями
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Точка входа main.js только импортирует и инициализирует
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Все скрипты — ES modules с type=\"module\"\n- [ ] Нет глобальных переменных в window\n- [ ] Логичная структура папок js/

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Разбей Todo App на модули: storage.js, todo.js, render.js, main.js
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. api.js — функции fetch с экспортом
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Переименование при импорте: import { fetchPosts as getPosts }
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Запуск через Live Server (модули требуют HTTP, не file://)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 07 day 5: es modules structure\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Формы и API вместе

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~35м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Notes Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Связка HTML-форм и fetch — типичный сценарий создания данных на сервере. Перехвати событие submit, вызови e.preventDefault(), собери данные из полей и отправь POST-запрос с body: JSON.stringify(formData) и заголовком Content-Type: application/json. Для форм с файлами удобнее FormData — он автоматически формирует multipart-тело. На время запроса отключай кнопку submit, чтобы пользователь не отправил дубликат.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Поиск по API при каждом нажатии клавиши создаёт лишнюю нагрузку. Debounce откладывает вызов функции до паузы в вводе (обычно 300 мс): пока пользователь печатает, запросы не уходят. Если запрос уже в полёте, а пользователь изменил запрос, старый ответ может прийти позже нового и перезаписать актуальные данные — race condition. AbortController решает это: передай signal в fetch и вызови abort() при новом вводе или в cleanup.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Optimistic UI обновляет интерфейс до ответа сервера («пост уже в списке»), создавая ощущение мгновенности. Но при ошибке сервера нужен rollback — убрать добавленный элемент и показать сообщение. Баланс между скоростью отклика и надёжностью — ключевой навык при работе с формами и API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Using Fetch — отправка данных\n- MDN: AbortController\n- learn.javascript.ru: debounce

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: форма + fetch требуют защиты от двойной отправки, debounce для поиска и отмены устаревших запросов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Форма «Добавить пост» → POST на JSONPlaceholder → добавь в список
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Поиск пользователей GitHub API с debounce 300ms
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Отмена предыдущего запроса при новом вводе (AbortController)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Disable кнопки submit на время запроса
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Показ success/error toast после отправки
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Реализуй debounce(fn, ms) самостоятельно или из learn.javascript.ru
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Покажи спиннер в поле поиска во время загрузки
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] POST отправляет корректный JSON\n- [ ] Debounce на поиске работает\n- [ ] UI не дублирует запросы при быстром вводе

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Форма «Добавить пост» → POST на JSONPlaceholder → добавь в список
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Поиск пользователей GitHub API с debounce 300ms
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Отмена предыдущего запроса при новом вводе (AbortController)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Disable кнопки submit на время запроса
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 07 day 6: forms api debounce\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Интеграционный проект

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~35м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Notes Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Интеграционный проект недели объединяет всё изученное: модули, localStorage, fetch, формы. Архитектурно раздели код на слои: api — HTTP-запросы и парсинг ответов, cache — чтение/запись в storage с TTL, ui — рендер DOM и обработка событий, app — связывание слоёв. Модуль api не должен знать о DOM, а ui не должен формировать URL запросов — так проще тестировать и менять каждую часть отдельно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Кэш с TTL (time-to-live) сохраняет объект { data, cachedAt } в localStorage. При загрузке сравни Date.now() - cachedAt с лимитом (например, 5 минут): если кэш свежий — покажи данные мгновенно, если нет — запроси с сервера и обнови кэш. При offline (можно симулировать в DevTools) покажи устаревший кэш с предупреждением вместо пустого экрана — это базовый offline-first подход.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Оборачивай асинхронные операции в try/catch на границе слоёв: пользователь должен видеть понятное сообщение об ошибке, а не пустую страницу. Простой retry — повторить запрос 2–3 раза с задержкой при сетевом сбое. На следующей неделе этот код перепишется на async/await и Promise-утилиты, но принципы слоёв и обработки ошибок останутся.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- web.dev: Storage for the web\n- MDN: Fetch API\n- learn.javascript.ru: Промисы — подготовка к неделе 8

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: зрелое клиентское приложение — это слои (api/cache/ui) плюс явная обработка ошибок, кэша и offline-сценариев.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Собери «Панель постов»: список + детали + форма создания
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Кэшируй список постов в localStorage на 5 минут
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. При offline (DevTools → Offline) покажи кэш и предупреждение
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Модули: api, cache, ui, app
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Финальный рефакторинг и коммит feat: posts dashboard
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Собери Notes Dashboard: заметки + погода + GitHub search
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-07-done на финальном коммите
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Полный CRUD UI (create + read, delete опционально)\n- [ ] Кэш с TTL работает\n- [ ] Модульная архитектура

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Собери «Панель постов»: список + детали + форма создания
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Кэшируй список постов в localStorage на 5 минут
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. При offline (DevTools → Offline) покажи кэш и предупреждение
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Модули: api, cache, ui, app
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 07 day 7: notes dashboard final\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Dashboard заметок — SPA на ванильном JS с модулями, localStorage и внешним API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подробное описание: docs/projects.md — Неделя 7

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции: локальные заметки (CRUD + persist), виджет погоды с API, поиск по GitHub users.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] ES modules, минимум 5 файлов\n- [ ] localStorage + Fetch к 2 API\n- [ ] Loading/error/empty states\n- [ ] Debounced search, form validation\n- [ ] Папка week-07/ с README и скриншотом\n- [ ] Заметки: create, edit, delete, persist между сессиями\n- [ ] Виджет погоды по городу (Open-Meteo или аналог)\n- [ ] GitHub user search с debounce и отменой запроса\n- [ ] Тег week-07-done на финальном коммите

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Как сохранить массив объектов в localStorage?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Почему fetch не reject при HTTP 404?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Разница named export и default export?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Зачем type=\"module\" и почему не file://?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Могу ли я отправить JSON POST через fetch?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Notes Dashboard** в `learning-log/week-07/`, осмысленная Git-история, тег `week-07-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nМодули, Fetch, localStorage — мини-SPA на ванильном JS\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-07-day-1", "label": "День 1 (Mon): localStorage и sessionStorage"}, {"id": "week-07-day-2", "label": "День 2 (Tue): JSON и работа с данными"}, {"id": "week-07-day-3", "label": "День 3 (Wed): Fetch API — основы"}, {"id": "week-07-day-4", "label": "День 4 (Thu): Работа с публичными API"}, {"id": "week-07-day-5", "label": "День 5 (Fri): ES-модули"}, {"id": "week-07-day-6", "label": "День 6 (Sat): Формы и API вместе"}, {"id": "week-07-day-7", "label": "День 7 (Sun): Интеграционный проект"}, {"id": "week-07-project", "label": "Проект недели"}, {"id": "week-07-review", "label": "Ревью-чеклист"}], "text": "Неделя 7: JavaScript — localStorage, Fetch, формы, модули ES Цель недели: научиться сохранять данные в браузере, работать с API и организовывать код в ES-модули. Литература: learn.javascript.ru: Fetch , MDN Web Storage , MDN JavaScript modules , JSONPlaceholder Guide , web.dev Storage for the web Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-07/ День 1 (Mon): localStorage и sessionStorage Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~35м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Notes Dashboard Теория Web Storage API даёт браузеру простое key-value хранилище, привязанное к origin (протокол + домен + порт). localStorage и sessionStorage работают одинаково по API, но различаютс…"} \ No newline at end of file +{"id": "week-07", "title": "Modules & API", "fullTitle": "Неделя 7: JavaScript — localStorage, Fetch, формы, модули ES", "html": "

                                                                                                                                                                                                                        Неделя 7: JavaScript — localStorage, Fetch, формы, модули ES

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: научиться сохранять данные в браузере, работать с API и организовывать код в ES-модули.\nЛитература: learn.javascript.ru: Fetch, MDN Web Storage, MDN JavaScript modules, JSONPlaceholder Guide, web.dev Storage for the web

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md\nGit: минимум 1 осмысленный коммит каждый день в learning-log/week-07/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): localStorage и sessionStorage

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Notes Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Web Storage API даёт браузеру простое key-value хранилище, привязанное к origin (протокол + домен + порт). localStorage и sessionStorage работают одинаково по API, но различаются временем жизни: localStorage сохраняет данные между сессиями, а sessionStorage очищается при закрытии вкладки. Оба интерфейса принимают только строки — если нужно сохранить объект или массив, сначала сериализуй его через JSON.stringify, а при чтении восстанови через JSON.parse.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Основные методы: setItem(key, value), getItem(key) (возвращает null, если ключа нет), removeItem(key) и clear(). API синхронный: каждая операция выполняется на main thread, поэтому не стоит записывать большие объёмы данных за раз. Типичный лимит — около 5 МБ на origin; при переполнении браузер выбросит QuotaExceededError.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для настроек UI (тема, язык, черновики форм) localStorage — естественный выбор. Но это не защищённое хранилище: любой JavaScript на странице (в том числе внедрённый через XSS) может прочитать все ключи. Пароли, JWT и API-ключи в localStorage хранить нельзя. Пользователь или расширение браузера могут вручную изменить значение в DevTools — поэтому JSON.parse всегда оборачивай в try/catch и задавай разумные значения по умолчанию при ошибке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: localStorage удобно представлять как блокнот, лежащий прямо в браузере пользователя, а не в твоём приложении. Блокнот привязан не к вкладке и не к сессии, а к конкретному origin — открыл тот же сайт неделю спустя, а записи всё ещё там. Но это чужой блокнот: любой скрипт на странице может его читать и писать, поэтому в нём нельзя хранить секреты, только то, что не страшно потерять или показать посторонним.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: сегодняшний навык — первый шаг к тому, чтобы приложение «помнило» пользователя без сервера и базы данных. На неделе к проекту Notes Dashboard localStorage станет основным хранилищем заметок, а на будущих неделях с backend ты увидишь, что именно осознание уязвимости localStorage к XSS объясняет, почему токены авторизации в реальных production-приложениях чаще хранят в httpOnly cookie, а не здесь.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: сохранение массива задач — localStorage.setItem('tasks', JSON.stringify(tasks)), восстановление — const saved = localStorage.getItem('tasks'); const tasks = saved ? JSON.parse(saved) : []. Проверка saved ? до парсинга защищает от попытки распарсить null, если ключ ещё не создавался — частая причина ошибки при первом запуске приложения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички думают, что localStorage может хранить объекты и массивы напрямую, и пишут localStorage.setItem('user', user) без JSON.stringify. На деле любое значение молча приводится к строке — объект превратится в бесполезную строку \"[object Object]\", из которой ничего не восстановить. Сериализация через JSON — не опция, а обязательный шаг, который отрабатывается в сегодняшней практике на функциях saveState/loadState.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Window.localStorage\n- MDN: Web Storage API\n- web.dev: Storage for the web

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: localStorage — удобный кэш для UI-состояния, но не сейф для секретов и не замена серверной базе данных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сохрани Todo-список в localStorage при каждом изменении
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. При загрузке страницы восстанови задачи из storage
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Кнопка «Очистить всё» — removeItem + обновление UI
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сохрани тему оформления (light/dark) между сессиями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Обработай случай битого JSON в getItem (try/catch)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай ключ week-07-notes — заготовка для проекта недели
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Вынеси работу со storage в функции saveState / loadState
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Данные переживают перезагрузку страницы\n- [ ] Объекты сериализуются через JSON\n- [ ] Ошибки парсинга обработаны gracefully

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сохрани Todo-список в localStorage при каждом изменении
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. При загрузке страницы восстанови задачи из storage
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Кнопка «Очистить всё» — removeItem + обновление UI
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сохрани тему оформления (light/dark) между сессиями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 07 day 1: localStorage persist\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Хранение паролей и токенов в localStorage — уязвимость XSS
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Забытый JSON.parse — строка \"[object Object]\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • QuotaExceededError при переполнении — редко, но возможно
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): JSON и работа с данными

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Notes Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        JSON (JavaScript Object Notation) — текстовый формат обмена данными между клиентом, сервером и файлами. Он поддерживает объекты, массивы, строки, числа, true/false и null, но не функции, undefined и комментарии. При JSON.stringify объекты Date превращаются в ISO-строки, а undefined в свойствах объекта просто опускаются — это важно помнить при экспорте данных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Метод JSON.stringify(obj, replacer, space) умеет фильтровать поля (через массив ключей или функцию-replacer) и форматировать вывод: space: 2 делает JSON читаемым для человека при отладке. Обратная операция — JSON.parse, которая бросает SyntaxError на невалидном тексте. Импорт из файла всегда требует валидации: проверь наличие обязательных полей, типы и допустимые значения до того, как смешаешь чужие данные со своим состоянием.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        В приложениях с localStorage данные со временем меняют форму. Добавь поле schemaVersion в сохраняемый объект — при загрузке сравни версию и при необходимости мигрируй старый формат в новый. Обновления списков объектов делай иммутабельно: items.map(item => item.id === id ? { ...item, title } : item) вместо прямой мутации элемента массива. Так проще отслеживать изменения и избегать побочных эффектов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: JSON удобно представлять как универсальный «переводчик» между живыми JS-объектами в памяти и текстом, который можно сохранить в файл, отправить по сети или положить в localStorage. stringify — перевод «объект → текст», parse — обратный перевод «текст → объект». Важно помнить, что перевод не идеален: некоторые вещи (функции, undefined, Date как объект) в JSON не выражаются напрямую и либо теряются, либо превращаются в упрощённую форму (строку).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: JSON — универсальный язык обмена данными, на котором будет разговаривать твой код с любым сервером на неделе 8 и дальше: любой ответ от Fetch API, который ты получишь завтра, придёт именно в этом формате. А привычка валидировать импортированные данные до того, как смешать их со своим состоянием, защищает приложение от падения при получении неожиданного формата — что произойдёт неизбежно при работе с реальными внешними данными.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: экспорт задач для скачивания — JSON.stringify(tasks, null, 2) создаёт читаемый, отформатированный текст с отступом в 2 пробела вместо сплошной строки — это то самое space, которое пригодится при отладке в консоли. При импорте того же файла JSON.parse(text) вернёт исходный массив объектов, и на этом этапе стоит сразу проверить, что каждый элемент содержит обязательные поля id, title.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички считают, что раз JSON.parse(JSON.stringify(obj)) возвращает «тот же» объект, значит JSON сохраняет абсолютно всё. На деле это популярный, но неполный способ глубокого клонирования: методы объекта, undefined-свойства и специальные типы вроде Map/Set при этом теряются молча, без предупреждения. Для задач сегодняшней практики (Todo-объекты с простыми полями) это не проблема, но важно понимать границу метода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Working with JSON\n- MDN: JSON.stringify()\n- learn.javascript.ru: Формат JSON

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: JSON — контракт обмена данными; валидация и версионирование схемы защищают приложение от битых импортов и устаревших сохранений.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Экспорт Todo в JSON-файл (download через Blob + URL.createObjectURL)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Импорт: <input type=\"file\"> → FileReader → parse → merge в список
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Функция validateTodo(data) — проверка обязательных полей
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Статистика: группировка задач по дате создания
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Миграция данных: если версия схемы старая — обнови формат
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь exportedAt в экспортируемый JSON
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Отклони импорт с понятным сообщением при невалидном файле
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Экспорт/импорт JSON работает\n- [ ] Валидация отклоняет невалидные данные\n- [ ] Иммутабельные обновления, не мутация массива напрямую

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Экспорт Todo в JSON-файл (download через Blob + URL.createObjectURL)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Импорт: <input type=\"file\"> → FileReader → parse → merge в список
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Функция validateTodo(data) — проверка обязательных полей
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Статистика: группировка задач по дате создания
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 07 day 2: json import export\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): Fetch API — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Notes Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Fetch API — современный способ делать HTTP-запросы из браузера. Вызов fetch(url) сразу возвращает Promise, который разрешается объектом Response, ещё до того как тело ответа полностью загружено. Чтобы получить JSON, нужна вторая асинхронная операция: response.json(), которая тоже возвращает Promise. Типичная цепочка: fetch(url).then(r => r.json()).then(data => ...).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Важная особенность: fetch не отклоняет Promise при HTTP-ошибках вроде 404 или 500. Promise reject происходит только при сетевых сбоях (нет интернета, CORS, таймаут DNS). Поэтому всегда проверяй response.ok (это shorthand для статусов 200–299) и обрабатывай неуспешные ответы явно — выброси ошибку или верни понятное сообщение пользователю.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для POST-запросов передай объект опций вторым аргументом: method: 'POST', headers: { 'Content-Type': 'application/json' } и body: JSON.stringify(data). Без правильного Content-Type сервер может не распознать тело как JSON. Для обучения удобен JSONPlaceholder — бесплатный mock REST API без регистрации, имитирующий посты, пользователей и комментарии.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: fetch удобно представлять как письмо, отправленное по почте, а не телефонный звонок. Ты не получаешь ответ мгновенно — Promise возвращается сразу, но означает лишь «письмо отправлено», а не «ответ получен». .then() — это момент, когда почтальон приносит ответ; если ответов нужно два (сначала «получил ли сервер запрос вообще», потом «что внутри тела ответа»), их приходится ждать по очереди, отсюда и двухступенчатая цепочка fetch(url).then(r => r.json()).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: Fetch — единственный способ получить данные с сервера из браузера, и с этого дня почти каждый проект курса будет обращаться к какому-нибудь API. На неделе 8 та же цепочка .then() перепишется на async/await — синтаксически проще, но модель поведения (Promise, отдельная обработка сетевых и HTTP-ошибок) останется точно такой же, так что сегодняшнее понимание не станет устаревшим.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: fetch('https://jsonplaceholder.typicode.com/posts/9999') вернёт успешно разрешённый Promise с response.status === 404, а не ошибку — сеть отработала штатно, просто сервер сообщил «не найдено». Только fetch('https://несуществующий-домен.test') (сеть недоступна) действительно приведёт к .catch().

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: самая частая ошибка новичков — писать fetch(url).then(data => console.log(data.title)), ожидая сразу получить готовый объект. На деле первый .then() получает объект Response (метаданные: статус, заголовки), а не тело ответа — тело нужно отдельно распарсить через response.json(), который тоже асинхронный и требует своего .then(). Именно эта двухступенчатая цепочка отрабатывается в сегодняшней функции fetchJson.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Fetch\n- MDN: Using Fetch\n- JSONPlaceholder Guide

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: fetch различает «сеть упала» (reject) и «сервер ответил ошибкой» (resolve с ok: false) — проверяй оба случая.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Загрузи посты с JSONPlaceholder
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Отобрази список заголовков в DOM
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Обработай loading state (текст «Загрузка...») и error state
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. POST новый пост на API, выведи ответ в Console
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Используй async/await (предпросмотр, углубление на неделе 8)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай функцию fetchJson(url) с проверкой response.ok
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Покажи empty state, если массив постов пуст
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Данные с API отображаются в UI\n- [ ] Обработаны loading и error\n- [ ] Проверяется response.ok

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Загрузи посты с JSONPlaceholder
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Отобрази список заголовков в DOM
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Обработай loading state (текст «Загрузка...») и error state
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. POST новый пост на API, выведи ответ в Console
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 07 day 3: fetch api basics\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): Работа с публичными API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Notes Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Публичные REST API организуют данные вокруг ресурсов — сущностей вроде «пользователь», «пост» или «город». URL описывает что запрашиваешь (/users/42), а HTTP-метод — какое действие выполняешь (GET — прочитать, POST — создать). Ответ сервера сопровождается статус-кодом: 200 — успех, 201 — создано, 400 — ошибка клиента, 404 — не найдено, 500 — ошибка сервера. Умение читать статус и тело ответа — базовый навык интеграции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Параметры запроса передаются в query string: ?q=moscow&page=2. Спецсимволы и пробелы кодируй через URLSearchParams, а не вручную — иначе поиск по «New York» сломается. Перед интеграцией изучи документацию API: какие endpoints доступны, какие поля обязательны, есть ли лимиты на количество запросов (rate limiting). OpenAPI/Swagger-спецификация — стандартный формат, где всё это описано машиночитаемо.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CORS (Cross-Origin Resource Sharing) — механизм безопасности браузера. Если твой сайт на localhost:5500, а API на другом домене, браузер спросит сервер: «разрешён ли этот origin?». Если сервер не вернёт нужные заголовки (Access-Control-Allow-Origin), fetch заблокируется — это не баг твоего кода, а политика браузера. API-ключи в production-коде на клиенте видны всем — для секретных ключей нужен backend-прокси.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: REST API удобно представлять как каталог товаров в магазине с чёткой системой адресов: URL — это адрес полки (/users/42 — полка «пользователь номер 42»), а HTTP-метод — действие с этой полкой (GET — посмотреть, POST — положить новое, DELETE — убрать). Такая единообразная адресация позволяет, не читая документацию каждого конкретного API с нуля, догадаться о структуре по аналогии с уже знакомыми.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: реальные проекты почти всегда строятся вокруг стороннего или собственного API — умение быстро прочитать документацию, понять доступные endpoints и правильно интерпретировать статус-коды экономит часы отладки. CORS — это то, с чем ты гарантированно столкнёшься, как только начнёшь подключать любой внешний сервис, и важно сразу понимать: ошибка CORS в консоли означает «сервер не разрешил», а не «код неправильный».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: запрос погоды для города с пробелом в названии — fetch('https://api.example.com/weather?city=' + encodeURIComponent('Нижний Новгород')) или через URLSearchParams: const params = new URLSearchParams({ city: 'Нижний Новгород' }); fetch('https://api.example.com/weather?' + params). Без кодирования пробел и кириллица в URL могут сломать запрос или интерпретироваться сервером неправильно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички, столкнувшись с ошибкой CORS в консоли, пытаются «исправить» её в своём JS-коде — но CORS настраивается на сервере, а не на клиенте, и обойти его на фронтенде штатными средствами невозможно (и не нужно, это защита пользователя). Если сервер действительно не поддерживает CORS для твоего случая, единственный легитимный вариант — свой backend-прокси, который сегодняшняя практика пока не требует, но важно понимать причину ограничения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: CORS\n- MDN: HTTP Overview\n- Open-Meteo API

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: интеграция с API начинается с чтения документации и понимания HTTP-семантики, а не с написания fetch.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Погода: Open-Meteo API — без ключа
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Форма поиска города → fetch → отображение температуры и иконки
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Пагинация: загрузи страницы постов JSONPlaceholder по кнопке «Ещё»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Обработай 404 и сетевую ошибку разными сообщениями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Дебаг запросов в DevTools → Network
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. GitHub Users API: поиск по логину — заготовка для проекта
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Документируй используемые endpoints в комментарии api.js
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Реальный API интегрирован в UI\n- [ ] Пользователь видит понятные сообщения об ошибках\n- [ ] Network panel использован для отладки

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Погода: Open-Meteo API — без ключа
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Форма поиска города → fetch → отображение температуры и иконки
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Пагинация: загрузи страницы постов JSONPlaceholder по кнопке «Ещё»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Обработай 404 и сетевую ошибку разными сообщениями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 07 day 4: public apis weather github\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): ES-модули

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Notes Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        ES-модули — стандартный способ организации JavaScript-кода в файлах с явными зависимостями. Каждый файл — отдельный модуль со своей областью видимости: переменные не попадают в глобальный window. Чтобы сделать функцию или константу доступной снаружи, используй export. Импорт: import { fetchPosts } from './api.js' для именованного экспорта или import render from './render.js' для default.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        В HTML подключай модули через <script type=\"module\" src=\"main.js\">. Такой скрипт выполняется в strict mode, откладывается (defer) и загружается как модуль — браузер сам разрешит дерево зависимостей. В пути импорта обязательно указывай расширение .js — в отличие от bundler-ов, нативные модули в браузере этого требуют. Открытие файла через file:// не сработает из-за CORS; нужен локальный HTTP-сервер (Live Server, npx serve).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Именованный export предпочтителен, когда из файла экспортируется несколько сущностей — имена явные при импорте и рефакторинге. Default export удобен для «главной» сущности файла (один компонент, один класс). Типичная структура проекта: api/ — запросы, ui/ — рендер DOM, utils/ — хелперы, main.js — точка входа, которая только связывает модули.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: до модулей весь JS-код жил в одной большой общей комнате (глобальная область видимости window) — любая переменная была видна отовсюду, и случайное совпадение имён в разных файлах могло незаметно всё сломать. Модули — это отдельные комнаты с закрытыми дверями: то, что не экспортировано явно через export, остаётся приватным для файла, а import — единственный «дверной проём», через который одна комната может попросить что-то у другой.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: структура api/ui/utils/main.js — это упрощённая версия архитектуры, которую ты увидишь в любом современном фронтенд-проекте, включая React-приложения дальше по курсу: разделение на слои по ответственности, а не по случайному принципу «файл разросся — создам новый». Умение аккуратно резать монолитный app.js на модули — прямая тренировка рефакторинга больших кодовых баз.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: storage.js экспортирует export function saveTasks(tasks) {...} и export function loadTasks() {...}, а main.js импортирует import { saveTasks, loadTasks } from './storage.js'. Такой файл storage.js можно переиспользовать в другом проекте без единой правки — он не знает ничего о DOM или конкретных задачах, только про чтение/запись данных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички забывают указать .js в пути импорта (import { x } from './utils' вместо './utils.js') по привычке из bundler-based проектов (Webpack, Vite), где расширение можно опустить. Нативные ES-модули в браузере таких «магических» разрешений путей не делают — без явного расширения браузер выдаст ошибку загрузки модуля, что стоит сразу проверить при первом запуске через Live Server.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Модули\n- MDN: JavaScript modules\n- javascript.info: Модули

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: модули превращают монолитный скрипт в граф зависимостей с изолированными областями видимости — основа масштабируемого фронтенда.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Разбей Todo App на модули: storage.js, todo.js, render.js, main.js
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. api.js — функции fetch с экспортом
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Переименование при импорте: import { fetchPosts as getPosts }
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Запуск через Live Server (модули требуют HTTP, не file://)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Циклические зависимости — избегай, рефакторинг при необходимости
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай week-07/js/ с 5+ модулями
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Точка входа main.js только импортирует и инициализирует
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Все скрипты — ES modules с type=\"module\"\n- [ ] Нет глобальных переменных в window\n- [ ] Логичная структура папок js/

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Разбей Todo App на модули: storage.js, todo.js, render.js, main.js
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. api.js — функции fetch с экспортом
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Переименование при импорте: import { fetchPosts as getPosts }
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Запуск через Live Server (модули требуют HTTP, не file://)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 07 day 5: es modules structure\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Формы и API вместе

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Notes Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Связка HTML-форм и fetch — типичный сценарий создания данных на сервере. Перехвати событие submit, вызови e.preventDefault(), собери данные из полей и отправь POST-запрос с body: JSON.stringify(formData) и заголовком Content-Type: application/json. Для форм с файлами удобнее FormData — он автоматически формирует multipart-тело. На время запроса отключай кнопку submit, чтобы пользователь не отправил дубликат.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Поиск по API при каждом нажатии клавиши создаёт лишнюю нагрузку. Debounce откладывает вызов функции до паузы в вводе (обычно 300 мс): пока пользователь печатает, запросы не уходят. Если запрос уже в полёте, а пользователь изменил запрос, старый ответ может прийти позже нового и перезаписать актуальные данные — race condition. AbortController решает это: передай signal в fetch и вызови abort() при новом вводе или в cleanup.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Optimistic UI обновляет интерфейс до ответа сервера («пост уже в списке»), создавая ощущение мгновенности. Но при ошибке сервера нужен rollback — убрать добавленный элемент и показать сообщение. Баланс между скоростью отклика и надёжностью — ключевой навык при работе с формами и API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: debounce удобно представлять как секретаря, который не бежит выполнять поручение при каждом слове, а ждёт паузы в речи и выполняет только последнюю, окончательную просьбу. Применительно к поиску: пока пользователь печатает «Москва» по буквам, отправлять запрос на каждую букву («М», «Мо», «Мос»...) бессмысленно — нужен только финальный запрос, когда ввод остановился хотя бы на 300 мс.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: debounce и AbortController — это база для любого «живого» поиска в реальных приложениях, от простого автокомплита до сложных дашбордов. Race condition (когда устаревший ответ приходит позже нового и портит UI) — один из самых незаметных багов в асинхронном коде: тесты часто его не ловят, а пользователи с медленным интернетом сталкиваются регулярно. Умение защититься от него сейчас избавит от часов отладки в будущих проектах.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: без debounce поиск пользователей GitHub при вводе «cursor» отправит 6 запросов подряд (по одному на каждую букву), и если ответ на «c» придёт позже ответа на «cursor» (сеть непредсказуема), список покажет результаты для одной буквы поверх правильных. С debounce(search, 300) уйдёт только один запрос — после того как пользователь на 300 мс перестал печатать.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички считают, что достаточно просто отключить кнопку submit на время запроса, чтобы избежать всех проблем с повторными действиями. Но при быстром вводе в поле поиска (без кнопки) проблема остаётся — race condition возникает именно между несколькими автоматическими запросами, а не только между кликами по кнопке; решает её именно AbortController.abort() для устаревших запросов, что и отрабатывается в сегодняшней практике.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Using Fetch — отправка данных\n- MDN: AbortController\n- learn.javascript.ru: debounce

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: форма + fetch требуют защиты от двойной отправки, debounce для поиска и отмены устаревших запросов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Форма «Добавить пост» → POST на JSONPlaceholder → добавь в список
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Поиск пользователей GitHub API с debounce 300ms
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Отмена предыдущего запроса при новом вводе (AbortController)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Disable кнопки submit на время запроса
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Показ success/error toast после отправки
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Реализуй debounce(fn, ms) самостоятельно или из learn.javascript.ru
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Покажи спиннер в поле поиска во время загрузки
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] POST отправляет корректный JSON\n- [ ] Debounce на поиске работает\n- [ ] UI не дублирует запросы при быстром вводе

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Форма «Добавить пост» → POST на JSONPlaceholder → добавь в список
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Поиск пользователей GitHub API с debounce 300ms
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Отмена предыдущего запроса при новом вводе (AbortController)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Disable кнопки submit на время запроса
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 07 day 6: forms api debounce\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Интеграционный проект

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Notes Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Интеграционный проект недели объединяет всё изученное: модули, localStorage, fetch, формы. Архитектурно раздели код на слои: api — HTTP-запросы и парсинг ответов, cache — чтение/запись в storage с TTL, ui — рендер DOM и обработка событий, app — связывание слоёв. Модуль api не должен знать о DOM, а ui не должен формировать URL запросов — так проще тестировать и менять каждую часть отдельно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Кэш с TTL (time-to-live) сохраняет объект { data, cachedAt } в localStorage. При загрузке сравни Date.now() - cachedAt с лимитом (например, 5 минут): если кэш свежий — покажи данные мгновенно, если нет — запроси с сервера и обнови кэш. При offline (можно симулировать в DevTools) покажи устаревший кэш с предупреждением вместо пустого экрана — это базовый offline-first подход.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Оборачивай асинхронные операции в try/catch на границе слоёв: пользователь должен видеть понятное сообщение об ошибке, а не пустую страницу. Простой retry — повторить запрос 2–3 раза с задержкой при сетевом сбое. На следующей неделе этот код перепишется на async/await и Promise-утилиты, но принципы слоёв и обработки ошибок останутся.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: зрелое приложение недели удобно представлять как небольшую компанию с чётким разделением обязанностей: api — «отдел закупок», который умеет только ходить наружу за данными и ничего не знает про интерфейс; cache — «склад», хранящий недавно полученное для быстрой выдачи; ui — «витрина», отвечающая только за то, что видит покупатель; app — «менеджер», который командует остальными отделами, но сам ничего не делает руками. Каждый отдел можно заменить или протестировать отдельно, не трогая остальные.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: эта слоистая архитектура — не искусственное упражнение, а прямая репетиция того, как строятся production-приложения: разделение на data/network/presentation слои встречается и в vanilla JS, и в React, и в мобильной разработке. Кэш с TTL и offline-first подход — реальные требования, которые проверяющие (и будущие работодатели) ожидают видеть в серьёзном портфолио-проекте.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: при повторном открытии дашборда функция getPosts() сначала проверяет кэш — const cached = JSON.parse(localStorage.getItem('posts_cache')); if (cached && Date.now() - cached.cachedAt < 5 * 60 * 1000) return cached.data; — и только если кэш устарел или отсутствует, идёт в сеть за свежими данными и обновляет cachedAt.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение: новички смешивают весь код в одном app.js, где fetch, обработка ответа и обновление DOM идут подряд в одной функции — работает, пока проект маленький, но при добавлении кэша или изменении источника данных приходится переписывать всё сразу. Чёткое разделение на слои — не бюрократия, а страховка: изменение источника данных (например, переход с JSONPlaceholder на реальный backend) в правильно организованном проекте затронет только api.js, что и является целью финального рефакторинга в сегодняшней практике.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- web.dev: Storage for the web\n- MDN: Fetch API\n- learn.javascript.ru: Промисы — подготовка к неделе 8

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: зрелое клиентское приложение — это слои (api/cache/ui) плюс явная обработка ошибок, кэша и offline-сценариев.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Собери «Панель постов»: список + детали + форма создания
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Кэшируй список постов в localStorage на 5 минут
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. При offline (DevTools → Offline) покажи кэш и предупреждение
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Модули: api, cache, ui, app
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Финальный рефакторинг и коммит feat: posts dashboard
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Собери Notes Dashboard: заметки + погода + GitHub search
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-07-done на финальном коммите
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Полный CRUD UI (create + read, delete опционально)\n- [ ] Кэш с TTL работает\n- [ ] Модульная архитектура

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Собери «Панель постов»: список + детали + форма создания
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Кэшируй список постов в localStorage на 5 минут
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. При offline (DevTools → Offline) покажи кэш и предупреждение
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Модули: api, cache, ui, app
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 07 day 7: notes dashboard final\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Dashboard заметок — SPA на ванильном JS с модулями, localStorage и внешним API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подробное описание: docs/projects.md — Неделя 7

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции: локальные заметки (CRUD + persist), виджет погоды с API, поиск по GitHub users.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] ES modules, минимум 5 файлов\n- [ ] localStorage + Fetch к 2 API\n- [ ] Loading/error/empty states\n- [ ] Debounced search, form validation\n- [ ] Папка week-07/ с README и скриншотом\n- [ ] Заметки: create, edit, delete, persist между сессиями\n- [ ] Виджет погоды по городу (Open-Meteo или аналог)\n- [ ] GitHub user search с debounce и отменой запроса\n- [ ] Тег week-07-done на финальном коммите

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Как сохранить массив объектов в localStorage?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Почему fetch не reject при HTTP 404?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Разница named export и default export?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Зачем type=\"module\" и почему не file://?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Могу ли я отправить JSON POST через fetch?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Notes Dashboard** в `learning-log/week-07/`, осмысленная Git-история, тег `week-07-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nМодули, Fetch, localStorage — мини-SPA на ванильном JS\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-07-day-1", "label": "День 1 (Mon): localStorage и sessionStorage"}, {"id": "week-07-day-2", "label": "День 2 (Tue): JSON и работа с данными"}, {"id": "week-07-day-3", "label": "День 3 (Wed): Fetch API — основы"}, {"id": "week-07-day-4", "label": "День 4 (Thu): Работа с публичными API"}, {"id": "week-07-day-5", "label": "День 5 (Fri): ES-модули"}, {"id": "week-07-day-6", "label": "День 6 (Sat): Формы и API вместе"}, {"id": "week-07-day-7", "label": "День 7 (Sun): Интеграционный проект"}, {"id": "week-07-project", "label": "Проект недели"}, {"id": "week-07-review", "label": "Ревью-чеклист"}], "text": "Неделя 7: JavaScript — localStorage, Fetch, формы, модули ES Цель недели: научиться сохранять данные в браузере, работать с API и организовывать код в ES-модули. Литература: learn.javascript.ru: Fetch , MDN Web Storage , MDN JavaScript modules , JSONPlaceholder Guide , web.dev Storage for the web Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-07/ День 1 (Mon): localStorage и sessionStorage Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Notes Dashboard Теория Web Storage API даёт браузеру простое key-value хранилище, привязанное к origin (протокол + домен + порт). localStorage и sessionStorage работают одинаково по API, но различаются …"} \ No newline at end of file diff --git a/docs/weeks/08.json b/docs/weeks/08.json index 8470b1c..131e510 100644 --- a/docs/weeks/08.json +++ b/docs/weeks/08.json @@ -1 +1 @@ -{"id": "week-08", "title": "Async & HTTP", "fullTitle": "Неделя 8: Async JS — promises, event loop, HTTP, API patterns", "html": "

                                                                                                                                                                                                                        Неделя 8: Async JS — promises, event loop, HTTP, API patterns

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: глубоко понять асинхронность в JavaScript, Promises, Event Loop и паттерны работы с API.\nЛитература: Kyle Simpson «You Don't Know JS: Async & Performance», learn.javascript.ru: Промисы, MDN Event Loop, JavaScript.info: Event loop, Philip Roberts: What the heck is the event loop?

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md\nGit: минимум 1 осмысленный коммит каждый день в learning-log/week-08/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Асинхронность и Event Loop

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Movie Catalog

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        JavaScript однопоточен: в каждый момент времени выполняется только один фрагмент кода на main thread. Синхронные операции (циклы, тяжёлые вычисления) блокируют интерфейс — кнопки не реагируют, анимации замирают. Асинхронность решает это: долгие задачи (таймеры, сетевые запросы, чтение файлов) делегируются Web APIs браузера, а результат возвращается через колбэки, когда main thread освободится.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Event Loop — механизм, который координирует выполнение. Call stack выполняет текущий синхронный код. Когда стек пуст, Loop проверяет очереди задач. Сначала выполняются microtasks (колбэки Promise: .then, .catch, queueMicrotask), и только потом macrotasks (setTimeout, setInterval, I/O). Поэтому Promise.resolve().then(...) всегда выполнится раньше setTimeout(fn, 0) — даже с нулевой задержкой.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Классическая ловушка — думать, что setTimeout(fn, 0) выполнится «сразу». На самом деле он попадёт в macrotask queue и дождётся завершения всего синхронного кода и всех microtasks. Понимание этого порядка — основа отладки «почему console.log выводится не в том порядке, который я ожидал». Визуализатор Loupe помогает увидеть движение задач по очередям.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Введение: колбэки\n- javascript.info: Event loop\n- MDN: Event Loop\n- Loupe — визуализация Event Loop

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: microtasks (Promise) всегда опережают macrotasks (setTimeout) — запомни это правило, и половина async-багов исчезнет.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Предскажи порядок вывода 5 задач с console.log, setTimeout, Promise.resolve().then
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Проверь в браузере, объясни через Event Loop
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Нарисуй диаграмму выполнения в блокноте
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Пройди 10+ примеров на javascript.info/event-loop
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Запиши правило: microtasks перед macrotasks
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь queueMicrotask в пример — сравни с Promise.resolve().then
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Сохрани конспект Event Loop в week-08/notes.md
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Могу предсказать порядок вывода в 4 из 5 примеров\n- [ ] Понимаю разницу microtask и macrotask\n- [ ] Есть конспект Event Loop своими словами

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Предскажи порядок вывода 5 задач с console.log, setTimeout, Promise.resolve().then
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Проверь в браузере, объясни через Event Loop
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Нарисуй диаграмму выполнения в блокноте
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Пройди 10+ примеров на javascript.info/event-loop
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 08 day 1: event loop basics\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Думать, что setTimeout(0) выполняется мгновенно
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Блокировка main thread тяжёлыми вычислениями — UI замрёт
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Бесконечная рекурсия Promise.then — microtask starvation
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Promises — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Movie Catalog

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Promise — объект-обёртка над результатом асинхронной операции, который ещё неизвестен. У Promise три состояния: pending (ожидание), fulfilled (успех) и rejected (ошибка). Переход из pending возможен только один раз — после resolve или reject состояние не меняется. Это делает Promise предсказуемым контрактом: либо данные, либо ошибка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Создание: new Promise((resolve, reject) => { ... }). Потребление: .then(onFulfilled) для успеха, .catch(onRejected) для ошибок, .finally(onFinally) для cleanup в любом случае (скрыть loader, сбросить флаг загрузки). Каждый .then возвращает новый Promise — поэтому цепочки .then().then().catch() читаются сверху вниз без «callback hell» вложенных функций.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если .then-колбэк возвращает значение, следующий .then получит его. Если возвращает Promise, следующий .then дождётся его разрешения. Один .catch в конце цепочки перехватит reject из любого предыдущего звена. Promise.all([p1, p2]) запускает несколько Promise параллельно и ждёт все — но один reject роняет весь результат.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Промисы\n- learn.javascript.ru: Цепочка промисов\n- MDN: Promise

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: Promise — это цепочка, а не вложенность; .then возвращает новый Promise, и один .catch обслуживает всю цепочку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Оберни setTimeout в функцию delay(ms) → Promise
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Цепочка: delay(1000) → «Шаг 1» → delay(500) → «Шаг 2»
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. fetch перепиши на .then без async/await
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Обработай reject: fetch несуществующего URL + catch
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Promise.all — загрузи posts и users параллельно
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь .finally для сброса loading state
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Верни значение из .then и прочитай его в следующем .then
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Цепочка then без callback hell\n- [ ] Ошибки ловятся в catch\n- [ ] Promise.all для параллельных запросов

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Оберни setTimeout в функцию delay(ms) → Promise
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Цепочка: delay(1000) → «Шаг 1» → delay(500) → «Шаг 2»
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. fetch перепиши на .then без async/await
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Обработай reject: fetch несуществующего URL + catch
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 08 day 2: promises chaining\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): async/await

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Movie Catalog

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        async/await — синтаксический сахар над Promise, делающий асинхронный код похожим на синхронный. Функция с ключевым словом async всегда возвращает Promise: даже return 42 превратится в Promise.resolve(42). Ключевое слово await можно использовать только внутри async-функции — оно приостанавливает выполнение только этой функции, отдавая управление Event Loop. Main thread при этом не блокируется.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Вместо .catch в цепочке используй try/catch вокруг await:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        try {\n  const data = await fetchJson(url);\n} catch (err) {\n  showError(err.message);\n}\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Главная ловушка — последовательный await в цикле: for (const id of ids) { await fetch(id) } выполнит N запросов по очереди. Если запросы независимы, собери массив Promise и дождись всех: await Promise.all(ids.map(id => fetch(id))). В ES-модулях доступен top-level await — можно писать const config = await fetch('/config.json') прямо в main.js без обёртки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Async/await\n- MDN: async function\n- javascript.info: Async/await

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: await не блокирует браузер — он лишь ставит на паузу текущую async-функцию, пока Promise не разрешится.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Рефакторинг fetch-функций на async/await
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Функция loadUserWithPosts(userId) — user, затем его posts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Параллельная загрузка 3 endpoints через Promise.all + await
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. try/catch с понятным сообщением для пользователя
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Async IIFE для top-level await в модуле
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сравни время: последовательный vs параллельный await (console.time)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Оберни api-слой недели 7 в async/await
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Весь API-слой на async/await\n- [ ] Параллельные запросы не последовательные без причины\n- [ ] try/catch на каждом публичном API-вызове

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Рефакторинг fetch-функций на async/await
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Функция loadUserWithPosts(userId) — user, затем его posts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Параллельная загрузка 3 endpoints через Promise.all + await
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. try/catch с понятным сообщением для пользователя
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 08 day 3: async await refactor\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): HTTP углублённо

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Movie Catalog

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        HTTP — протокол обмена сообщениями между клиентом и сервером. Каждый запрос состоит из метода, URL, заголовков и опционального тела. Ответ содержит статус-код, заголовки и тело. Методы несут семантику: GET читает ресурс (идемпотентен, кэшируем), POST создаёт новый, PUT/PATCH обновляют, DELETE удаляет. Понимание семантики помогает проектировать API и правильно обрабатывать ответы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Статус-коды сгруппированы: 1xx — информация, 2xx — успех (200 OK, 201 Created, 204 No Content), 3xx — перенаправление, 4xx — ошибка клиента (400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found), 5xx — ошибка сервера. Для UI важно различать 401 («войдите в систему») и 403 («у вас нет прав») — пользователю нужны разные сообщения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Заголовки передают метаданные: Content-Type описывает формат тела, Authorization — токен доступа, Cache-Control и ETag управляют кэшированием. CORS настраивается на сервере через заголовки вроде Access-Control-Allow-Origin. «Непростые» запросы (нестандартные заголовки, методы кроме GET/POST) вызывают preflight — браузер сначала отправит OPTIONS и спросит разрешение.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: HTTP Overview\n- MDN: CORS\n- MDN: HTTP response status codes

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: HTTP-метод + статус-код + заголовки — это язык, на котором клиент и сервер договариваются о результате операции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. В Network изучи headers реального запроса к API
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Реализуй wrapper api.get/post/put/delete с базовым URL
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь заголовок Content-Type: application/json автоматически
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Маппинг статусов в ошибки: ApiError с полем status
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Обработай 401 — сообщение «Требуется авторизация»
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Класс ApiError extends Error с status и body
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Логируй failed requests в console с status и url
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] API wrapper переиспользуемый\n- [ ] Разные HTTP-ошибки — разные сообщения UI\n- [ ] Понимаю CORS на уровне «почему fetch заблокирован»

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. В Network изучи headers реального запроса к API
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Реализуй wrapper api.get/post/put/delete с базовым URL
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь заголовок Content-Type: application/json автоматически
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Маппинг статусов в ошибки: ApiError с полем status
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 08 day 4: http api wrapper\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Паттерны работы с API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Movie Catalog

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Работа с API в production выходит за рамки простого fetch(url). Пагинация делит большие наборы данных на страницы: offset/limit (?page=2&limit=20) прост в реализации, но нестабилен при вставках новых записей; cursor-based пагинация (?after=lastId) надёжнее для лент и поиска. Retry с exponential backoff повторяет упавший запрос с растущей задержкой (1с, 2с, 4с), не перегружая сервер при временных сбоях.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Race condition возникает, когда быстрый новый запрос завершается раньше старого, но старый ответ приходит последним и перезаписывает актуальные данные. Решения: AbortController (отменить предыдущий fetch) или счётчик/request id (игнорировать устаревший ответ). Request deduplication не запускает второй идентичный запрос, пока первый ещё в полёте — полезно для кэширования в памяти.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Паттерн stale-while-revalidate: сначала покажи кэшированные данные (мгновенный отклик), затем обнови фоном. Skeleton UI резервирует место под контент во время загрузки, снижая layout shift (CLS). Эти приёмы превращают «голый fetch» в устойчивый клиентский слой данных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- JSON:API — Pagination\n- web.dev: Optimize LCP — skeleton и perceived performance\n- MDN: AbortController

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: надёжный API-клиент обрабатывает не только успех, но и повторы, гонки запросов, пагинацию и кэширование.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пагинация постов: кнопка «Загрузить ещё» с cursor (id последнего)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Retry: 3 попытки с задержкой 1s, 2s, 4s при сетевой ошибке
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. In-memory cache Map: повторный запрос того же URL — из кэша
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Skeleton UI на время загрузки, контент без layout shift
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Отмена устаревшего ответа: race condition при быстром поиске
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Реализуй fetchWithRetry(url, options, maxRetries)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Дедупликация: не запускай второй identical fetch, пока первый pending
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Retry реализован\n- [ ] Нет race condition в поиске\n- [ ] Pagination работает без дубликатов

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пагинация постов: кнопка «Загрузить ещё» с cursor (id последнего)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Retry: 3 попытки с задержкой 1s, 2s, 4s при сетевой ошибке
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. In-memory cache Map: повторный запрос того же URL — из кэша
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Skeleton UI на время загрузки, контент без layout shift
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 08 day 5: api patterns retry pagination\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Promise utilities

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Movie Catalog

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Помимо базового Promise.all, в JavaScript есть набор утилит для разных сценариев. Promise.allSettled ждёт завершения всех Promise и возвращает массив { status, value/reason } — идеально, когда нужны результаты нескольких независимых API, даже если часть упала. Promise.race отдаёт результат первого завершившегося Promise — удобно для timeout-обёртки. Promise.any возвращает первый успешный, игнорируя reject (если все упали — AggregateError).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Promise.all работает по принципу fail-fast: один reject ломает весь результат. Используй его, когда все данные обязательны (загрузка профиля + настроек одновременно). Promise.allSettled — когда частичный успех допустим (дашборд с виджетами от разных сервисов). Timeout через race: Promise.race([fetch(url), delay(5000).then(() => Promise.reject('timeout'))]).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Необработанный reject (unhandledrejection) — сигнал, что где-то забыли .catch или try/catch. В production повесь глобальный listener window.addEventListener('unhandledrejection', ...) для логирования. for await...of позволяет последовательно обрабатывать асинхронные итерируемые источники без гонки параллельных запросов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Promise.allSettled()\n- MDN: Promise.race()\n- learn.javascript.ru: Promise API

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: выбирай Promise-утилиту по сценарию — all для «всё или ничего», allSettled для «что получилось», race для таймаутов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Загрузи 5 URL через Promise.allSettled, покажи успешные и failed
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Timeout wrapper: withTimeout(promise, 5000) через Promise.race
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Последовательная обработка массива URL без Promise.all (for await)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Глобальный unhandledrejection listener — логирование
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг dashboard недели 7 с новыми паттернами
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сравни Promise.all vs allSettled на массиве с одним failed URL
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь timeout 10s на все fetch в api wrapper
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] allSettled и race использованы по назначению\n- [ ] Timeout на долгие запросы\n- [ ] Нет unhandled promise rejections в Console

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Загрузи 5 URL через Promise.allSettled, покажи успешные и failed
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Timeout wrapper: withTimeout(promise, 5000) через Promise.race
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Последовательная обработка массива URL без Promise.all (for await)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Глобальный unhandledrejection listener — логирование
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 08 day 6: promise utilities timeout\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Асинхронная архитектура

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Movie Catalog

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Асинхронная архитектура приложения определяет, как слои общаются между собой. API-слой возвращает данные или бросает типизированную ошибку (ApiError со статусом) — он не знает о DOM и не решает, показать спиннер или toast. UI-слой подписывается на состояние и рендерит соответствующий экран. Между ними — слой состояния с явными фазами: idle | loading | success | error | empty.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Явная state machine убирает «зависшие» экраны: в каждый момент UI находится ровно в одном состоянии, и переходы предсказуемы (loading → success или loading → error). Простой pub/sub (createAsyncState с subscribe/setState) даёт реактивность без фреймворка — задел на React hooks. При тестировании async-кода fetch можно подменить mock-функцией, возвращающей фиксированный Promise.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        На следующих неделях TypeScript добавит Promise<T> как контракт: async-функция документирует, какой тип данных вернётся. Сейчас зафиксируй принцип: асинхронность — это не только синтаксис, а разделение ответственности между запросом, состоянием и отображением.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- javascript.info: Промисы\n- patterns.dev: Observer Pattern\n- TypeScript Handbook: Generics — подготовка к неделе 10

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: async-архитектура — это явные состояния UI и чёткие границы между api, state и render.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реализуй хук-подобный паттерн createAsyncState() — subscribe на изменения
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. UI автоматически реагирует на idle/loading/success/error
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Интегрируй в проект «Каталог фильмов» (OMDb или TMDB free tier / mock)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Поиск + детали фильма + избранное в localStorage
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Code review своего async-кода по чеклисту
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Empty state: «Ничего не найдено» при пустом результате поиска
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-08-done на финальном коммите
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Явные состояния async-операций в UI\n- [ ] api / state / ui разделены\n- [ ] Проект работает без ошибок в Console

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реализуй хук-подобный паттерн createAsyncState() — subscribe на изменения
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. UI автоматически реагирует на idle/loading/success/error
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Интегрируй в проект «Каталог фильмов» (OMDb или TMDB free tier / mock)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Поиск + детали фильма + избранное в localStorage
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 08 day 7: movie catalog final\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Каталог фильмов — async SPA с поиском, деталями, избранным и robust error handling.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подробное описание: docs/projects.md — Неделя 8

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        API: OMDb (omdbapi.com) или mock JSON server.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] async/await + api wrapper + retry/timeout\n- [ ] Состояния loading/error/empty/data\n- [ ] Promise.all для параллельной загрузки деталей\n- [ ] Избранное в localStorage, синхронизация с UI\n- [ ] Папка week-08/ с README и скриншотом\n- [ ] Поиск по названию с debounce и отменой устаревших запросов\n- [ ] Карточка фильма: постер, год, рейтинг, описание\n- [ ] Избранное: add/remove, persist, отдельная вкладка или секция\n- [ ] Тег week-08-done на финальном коммите

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Объясни Event Loop на примере setTimeout + Promise?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Разница Promise.all и Promise.allSettled?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Когда await блокирует UI, а когда нет?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что такое CORS и кто его настраивает?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как отменить fetch-запрос?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Movie Catalog** в `learning-log/week-08/`, осмысленная Git-история, тег `week-08-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nAsync/await, HTTP, работа с REST API\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-08-day-1", "label": "День 1 (Mon): Асинхронность и Event Loop"}, {"id": "week-08-day-2", "label": "День 2 (Tue): Promises — основы"}, {"id": "week-08-day-3", "label": "День 3 (Wed): async/await"}, {"id": "week-08-day-4", "label": "День 4 (Thu): HTTP углублённо"}, {"id": "week-08-day-5", "label": "День 5 (Fri): Паттерны работы с API"}, {"id": "week-08-day-6", "label": "День 6 (Sat): Promise utilities"}, {"id": "week-08-day-7", "label": "День 7 (Sun): Асинхронная архитектура"}, {"id": "week-08-project", "label": "Проект недели"}, {"id": "week-08-review", "label": "Ревью-чеклист"}], "text": "Неделя 8: Async JS — promises, event loop, HTTP, API patterns Цель недели: глубоко понять асинхронность в JavaScript, Promises, Event Loop и паттерны работы с API. Литература: Kyle Simpson «You Don't Know JS: Async & Performance», learn.javascript.ru: Промисы , MDN Event Loop , JavaScript.info: Event loop , Philip Roberts: What the heck is the event loop? Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-08/ День 1 (Mon): Асинхронность и Event Loop Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Movie Catalog Теория JavaScript однопоточен: в каждый момент времени выполняется только один фрагмент кода на main thread. Синхронные операци…"} \ No newline at end of file +{"id": "week-08", "title": "Async & HTTP", "fullTitle": "Неделя 8: Async JS — promises, event loop, HTTP, API patterns", "html": "

                                                                                                                                                                                                                        Неделя 8: Async JS — promises, event loop, HTTP, API patterns

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: глубоко понять асинхронность в JavaScript, Promises, Event Loop и паттерны работы с API.\nЛитература: Kyle Simpson «You Don't Know JS: Async & Performance», learn.javascript.ru: Промисы, MDN Event Loop, JavaScript.info: Event loop, Philip Roberts: What the heck is the event loop?

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md\nGit: минимум 1 осмысленный коммит каждый день в learning-log/week-08/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Асинхронность и Event Loop

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Movie Catalog

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        JavaScript однопоточен: в каждый момент времени выполняется только один фрагмент кода на main thread. Синхронные операции (циклы, тяжёлые вычисления) блокируют интерфейс — кнопки не реагируют, анимации замирают. Асинхронность решает это: долгие задачи (таймеры, сетевые запросы, чтение файлов) делегируются Web APIs браузера, а результат возвращается через колбэки, когда main thread освободится.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Event Loop — механизм, который координирует выполнение. Call stack выполняет текущий синхронный код. Когда стек пуст, Loop проверяет очереди задач. Сначала выполняются microtasks (колбэки Promise: .then, .catch, queueMicrotask), и только потом macrotasks (setTimeout, setInterval, I/O). Поэтому Promise.resolve().then(...) всегда выполнится раньше setTimeout(fn, 0) — даже с нулевой задержкой.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Классическая ловушка — думать, что setTimeout(fn, 0) выполнится «сразу». На самом деле он попадёт в macrotask queue и дождётся завершения всего синхронного кода и всех microtasks. Понимание этого порядка — основа отладки «почему console.log выводится не в том порядке, который я ожидал». Визуализатор Loupe помогает увидеть движение задач по очередям.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Хорошая мысленная модель — ресторанная кухня с одним поваром (main thread) и официантами (Web APIs). Повар не может делать два блюда одновременно, но может передать заказ на гриль (таймер, сетевой запрос) официанту и продолжить резать овощи. Когда гриль готов, официант кладёт тарелку в очередь готовых блюд — повар заберёт её, как только освободится. Так же Event Loop не выполняет асинхронные операции сам — он лишь решает, когда вернуть управление колбэку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Понимание Event Loop критично не только для отладки порядка console.log. Это фундамент, на котором строятся Promise (дни 2–3 этой недели), рендеринг React (батчинг обновлений state — неделя 11) и производительность Node.js на бэкенде, где один процесс обслуживает тысячи соединений именно благодаря неблокирующей модели. Частое заблуждение новичков — думать, что Web Workers или async/await делают JavaScript многопоточным: на самом деле выполняется всё тот же один поток, просто задачи чередуются, а настоящий параллелизм (несколько ядер CPU) требует отдельных Worker-потоков с собственной памятью.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: console.log('A'); setTimeout(() => console.log('B'), 0); Promise.resolve().then(() => console.log('C')); console.log('D') выведет A, D, C, B — синхронный код первым, затем microtask C, затем macrotask B, даже с нулевой задержкой таймера. Именно такие цепочки предстоит разобрать в первом задании практики: предсказание порядка вывода тренирует эту модель до автоматизма, а диаграмма в блокноте (шаг 3) закрепляет её визуально.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Введение: колбэки\n- javascript.info: Event loop\n- MDN: Event Loop\n- Loupe — визуализация Event Loop

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: microtasks (Promise) всегда опережают macrotasks (setTimeout) — запомни это правило, и половина async-багов исчезнет.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Предскажи порядок вывода 5 задач с console.log, setTimeout, Promise.resolve().then
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Проверь в браузере, объясни через Event Loop
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Нарисуй диаграмму выполнения в блокноте
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Пройди 10+ примеров на javascript.info/event-loop
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Запиши правило: microtasks перед macrotasks
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь queueMicrotask в пример — сравни с Promise.resolve().then
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Сохрани конспект Event Loop в week-08/notes.md
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Могу предсказать порядок вывода в 4 из 5 примеров\n- [ ] Понимаю разницу microtask и macrotask\n- [ ] Есть конспект Event Loop своими словами

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Предскажи порядок вывода 5 задач с console.log, setTimeout, Promise.resolve().then
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Проверь в браузере, объясни через Event Loop
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Нарисуй диаграмму выполнения в блокноте
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Пройди 10+ примеров на javascript.info/event-loop
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 08 day 1: event loop basics\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Думать, что setTimeout(0) выполняется мгновенно
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Блокировка main thread тяжёлыми вычислениями — UI замрёт
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Бесконечная рекурсия Promise.then — microtask starvation
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Promises — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Movie Catalog

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Promise — объект-обёртка над результатом асинхронной операции, который ещё неизвестен. У Promise три состояния: pending (ожидание), fulfilled (успех) и rejected (ошибка). Переход из pending возможен только один раз — после resolve или reject состояние не меняется. Это делает Promise предсказуемым контрактом: либо данные, либо ошибка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Создание: new Promise((resolve, reject) => { ... }). Потребление: .then(onFulfilled) для успеха, .catch(onRejected) для ошибок, .finally(onFinally) для cleanup в любом случае (скрыть loader, сбросить флаг загрузки). Каждый .then возвращает новый Promise — поэтому цепочки .then().then().catch() читаются сверху вниз без «callback hell» вложенных функций.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если .then-колбэк возвращает значение, следующий .then получит его. Если возвращает Promise, следующий .then дождётся его разрешения. Один .catch в конце цепочки перехватит reject из любого предыдущего звена. Promise.all([p1, p2]) запускает несколько Promise параллельно и ждёт все — но один reject роняет весь результат.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Удобная мысленная модель — талон в химчистке: ты оставляешь вещи (запускаешь асинхронную операцию) и получаешь квиток (Promise) прямо сейчас, а не сами вещи. Квиток можно передать другому человеку и объяснить, что делать с готовым результатом (.then) или с проблемой (.catch) — сама операция при этом продолжает выполняться независимо от того, смотришь ты на квиток или нет.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это понимание — фундамент для async/await, который изучается уже завтра: await — это просто способ «подождать квиток», не потеряв читаемость кода. Позже, при работе с React Query или SWR, ты снова встретишь Promise как базовую единицу асинхронного состояния. Частое заблуждение — считать, что код внутри new Promise((resolve) => {...}) выполняется асинхронно: на самом деле executor запускается синхронно и немедленно, а асинхронной становится только реакция через .then.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример: new Promise((resolve) => { console.log('1'); resolve('done'); }).then(v => console.log(v)); console.log('2') выведет 1, 2, done — executor отработал сразу, а .then дождался, пока текущий синхронный код (лог '2') закончится. В практике дня ты обернёшь setTimeout в delay(ms) (шаг 1) — стандартный паттерн превращения callback-based API в Promise-based, который пригодится для любой асинхронной функции без нативной поддержки Promise.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ещё один нюанс, который легко упустить: Promise может завершиться только один раз — повторный вызов resolve после первого resolve или reject просто игнорируется движком. Это гарантирует, что .then никогда не сработает дважды с разными значениями, и делает Promise надёжнее «сырых» колбэков, которые можно вызвать сколько угодно раз по ошибке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Промисы\n- learn.javascript.ru: Цепочка промисов\n- MDN: Promise

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: Promise — это цепочка, а не вложенность; .then возвращает новый Promise, и один .catch обслуживает всю цепочку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Оберни setTimeout в функцию delay(ms) → Promise
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Цепочка: delay(1000) → «Шаг 1» → delay(500) → «Шаг 2»
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. fetch перепиши на .then без async/await
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Обработай reject: fetch несуществующего URL + catch
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Promise.all — загрузи posts и users параллельно
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь .finally для сброса loading state
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Верни значение из .then и прочитай его в следующем .then
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Цепочка then без callback hell\n- [ ] Ошибки ловятся в catch\n- [ ] Promise.all для параллельных запросов

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Оберни setTimeout в функцию delay(ms) → Promise
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Цепочка: delay(1000) → «Шаг 1» → delay(500) → «Шаг 2»
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. fetch перепиши на .then без async/await
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Обработай reject: fetch несуществующего URL + catch
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 08 day 2: promises chaining\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): async/await

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Movie Catalog

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        async/await — синтаксический сахар над Promise, делающий асинхронный код похожим на синхронный. Функция с ключевым словом async всегда возвращает Promise: даже return 42 превратится в Promise.resolve(42). Ключевое слово await можно использовать только внутри async-функции — оно приостанавливает выполнение только этой функции, отдавая управление Event Loop. Main thread при этом не блокируется.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Вместо .catch в цепочке используй try/catch вокруг await:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        try {\n  const data = await fetchJson(url);\n} catch (err) {\n  showError(err.message);\n}\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Главная ловушка — последовательный await в цикле: for (const id of ids) { await fetch(id) } выполнит N запросов по очереди. Если запросы независимы, собери массив Promise и дождись всех: await Promise.all(ids.map(id => fetch(id))). В ES-модулях доступен top-level await — можно писать const config = await fetch('/config.json') прямо в main.js без обёртки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленно async/await — это «закладка» в книге: await не останавливает всю программу, а лишь запоминает место в текущей функции и отдаёт управление дальше, чтобы вернуться сюда, когда результат будет готов. Другие функции, таймеры и обработчики событий продолжают работать как ни в чём не бывало — блокируется только логика внутри конкретной async-функции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Этот паттерн станет основным способом работы с данными на неделях 10–11: типизированные API-функции (Promise<T> в TypeScript) и хуки React (useEffect с async-логикой внутри) опираются именно на async/await, а не на явные цепочки .then. Частое заблуждение — думать, что await можно использовать где угодно: без async на функции или на верхнем уровне обычного скрипта (не ES-модуля) движок выбросит SyntaxError.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример цены последовательного await: 10 запросов по 200мс каждый в цикле for...of с await дадут итог около 2 секунд, потому что каждый следующий запрос стартует только после ответа предыдущего. Заменив на await Promise.all(ids.map(id => fetch(id))), все запросы уйдут параллельно, и итог сократится примерно до 200мс. Именно это сравнение — шаг 6 практики дня (console.time) — наглядно покажет цену необдуманной последовательности и станет личным аргументом в пользу параллельных await, когда данные независимы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Важно помнить и обратный случай: если второй запрос логически зависит от результата первого (например, сначала получить userId, потом по нему загрузить посты), последовательный await — не ошибка, а единственно верный вариант. Параллелить стоит только независимые операции — умение отличить одно от другого и есть суть архитектурного мышления, а не просто «await — плохо, Promise.all — хорошо».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Async/await\n- MDN: async function\n- javascript.info: Async/await

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: await не блокирует браузер — он лишь ставит на паузу текущую async-функцию, пока Promise не разрешится.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Рефакторинг fetch-функций на async/await
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Функция loadUserWithPosts(userId) — user, затем его posts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Параллельная загрузка 3 endpoints через Promise.all + await
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. try/catch с понятным сообщением для пользователя
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Async IIFE для top-level await в модуле
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сравни время: последовательный vs параллельный await (console.time)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Оберни api-слой недели 7 в async/await
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Весь API-слой на async/await\n- [ ] Параллельные запросы не последовательные без причины\n- [ ] try/catch на каждом публичном API-вызове

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Рефакторинг fetch-функций на async/await
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Функция loadUserWithPosts(userId) — user, затем его posts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Параллельная загрузка 3 endpoints через Promise.all + await
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. try/catch с понятным сообщением для пользователя
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 08 day 3: async await refactor\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): HTTP углублённо

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Movie Catalog

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        HTTP — протокол обмена сообщениями между клиентом и сервером. Каждый запрос состоит из метода, URL, заголовков и опционального тела. Ответ содержит статус-код, заголовки и тело. Методы несут семантику: GET читает ресурс (идемпотентен, кэшируем), POST создаёт новый, PUT/PATCH обновляют, DELETE удаляет. Понимание семантики помогает проектировать API и правильно обрабатывать ответы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Статус-коды сгруппированы: 1xx — информация, 2xx — успех (200 OK, 201 Created, 204 No Content), 3xx — перенаправление, 4xx — ошибка клиента (400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found), 5xx — ошибка сервера. Для UI важно различать 401 («войдите в систему») и 403 («у вас нет прав») — пользователю нужны разные сообщения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Заголовки передают метаданные: Content-Type описывает формат тела, Authorization — токен доступа, Cache-Control и ETag управляют кэшированием. CORS настраивается на сервере через заголовки вроде Access-Control-Allow-Origin. «Непростые» запросы (нестандартные заголовки, методы кроме GET/POST) вызывают preflight — браузер сначала отправит OPTIONS и спросит разрешение.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель HTTP — обмен письмами по строгим правилам почты: клиент пишет письмо (запрос) с адресом (URL), типом отправления (метод) и содержимым (тело), сервер отвечает своим письмом со штампом (статус-код) и вложениями (тело ответа). Оба участника не хранят состояние друг о друге между письмами — HTTP по своей природе stateless, поэтому авторизация передаётся заново в каждом запросе (заголовок Authorization), а не «запоминается» сервером автоматически.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это понимание пригодится сразу при проектировании api-wrapper (шаг 2 практики) и в дальнейшем — при работе с REST API на бэкенде и при чтении документации любого стороннего сервиса, которая всегда описана в терминах методов, статусов и заголовков. Частое заблуждение новичков — путать 401 и 403: 401 означает «сервер не знает, кто ты» (нет или истёк токен, нужен логин), а 403 — «сервер знает, кто ты, но тебе запрещено» (например, обычный пользователь пытается зайти в админку). UI должен обрабатывать эти случаи по-разному: 401 → редирект на страницу входа, 403 → сообщение «недостаточно прав».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример CORS: фронтенд на localhost:3000 обращается к API на api.example.com — браузер блокирует ответ, если сервер не прислал заголовок Access-Control-Allow-Origin: http://localhost:3000 (или *). Это не ошибка сети и не баг клиента, а защитный механизм браузера, который стоит увидеть своими глазами в шаге 1 практики через вкладку Network: найди среди заголовков реального запроса те, что относятся именно к CORS и кэшированию.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: HTTP Overview\n- MDN: CORS\n- MDN: HTTP response status codes

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: HTTP-метод + статус-код + заголовки — это язык, на котором клиент и сервер договариваются о результате операции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. В Network изучи headers реального запроса к API
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Реализуй wrapper api.get/post/put/delete с базовым URL
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь заголовок Content-Type: application/json автоматически
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Маппинг статусов в ошибки: ApiError с полем status
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Обработай 401 — сообщение «Требуется авторизация»
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Класс ApiError extends Error с status и body
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Логируй failed requests в console с status и url
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] API wrapper переиспользуемый\n- [ ] Разные HTTP-ошибки — разные сообщения UI\n- [ ] Понимаю CORS на уровне «почему fetch заблокирован»

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. В Network изучи headers реального запроса к API
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Реализуй wrapper api.get/post/put/delete с базовым URL
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь заголовок Content-Type: application/json автоматически
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Маппинг статусов в ошибки: ApiError с полем status
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 08 day 4: http api wrapper\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Паттерны работы с API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Movie Catalog

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Работа с API в production выходит за рамки простого fetch(url). Пагинация делит большие наборы данных на страницы: offset/limit (?page=2&limit=20) прост в реализации, но нестабилен при вставках новых записей; cursor-based пагинация (?after=lastId) надёжнее для лент и поиска. Retry с exponential backoff повторяет упавший запрос с растущей задержкой (1с, 2с, 4с), не перегружая сервер при временных сбоях.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Race condition возникает, когда быстрый новый запрос завершается раньше старого, но старый ответ приходит последним и перезаписывает актуальные данные. Решения: AbortController (отменить предыдущий fetch) или счётчик/request id (игнорировать устаревший ответ). Request deduplication не запускает второй идентичный запрос, пока первый ещё в полёте — полезно для кэширования в памяти.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Паттерн stale-while-revalidate: сначала покажи кэшированные данные (мгновенный отклик), затем обнови фоном. Skeleton UI резервирует место под контент во время загрузки, снижая layout shift (CLS). Эти приёмы превращают «голый fetch» в устойчивый клиентский слой данных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель здесь — работа диспетчера такси, а не одного водителя: диспетчер умеет распределять заказы (запросы), повторно назначать заказ при отказе водителя (retry), отменять устаревший заказ, если клиент уже уехал на другой машине (устаревший ответ при race condition), и показывать клиенту примерное время ожидания, пока машина едет (skeleton UI). Голый fetch(url) — это водитель без диспетчера: работает, пока всё идёт по плану, и ломается при малейшей нестабильности сети.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эти паттерны становятся особенно важны в реальных продакшен-приложениях и позже — в библиотеках вроде React Query или SWR, которые фактически реализуют stale-while-revalidate, retry и дедупликацию «из коробки»; понимание паттернов вручную объясняет, что происходит «под капотом» таких библиотек, а не заставляет воспринимать их как магию. Частое заблуждение — считать race condition редкой экзотикой: на практике она возникает в любом live-поиске с debounce, где пользователь быстро меняет запрос, и старый ответ может прийти позже нового.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: пользователь печатает «cat», затем быстро «dog» — уходят два запроса, но ответ на «cat» из-за сетевой задержки приходит позже ответа на «dog» и затирает актуальный результат неактуальным. Решение — AbortController.abort() на предыдущий запрос при старте нового, либо сравнение id запроса перед применением результата. Это именно тот сценарий, который нужно воспроизвести и исправить в шаге 5 практики дня — «отмена устаревшего ответа при быстром поиске».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- JSON:API — Pagination\n- web.dev: Optimize LCP — skeleton и perceived performance\n- MDN: AbortController

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: надёжный API-клиент обрабатывает не только успех, но и повторы, гонки запросов, пагинацию и кэширование.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пагинация постов: кнопка «Загрузить ещё» с cursor (id последнего)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Retry: 3 попытки с задержкой 1s, 2s, 4s при сетевой ошибке
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. In-memory cache Map: повторный запрос того же URL — из кэша
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Skeleton UI на время загрузки, контент без layout shift
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Отмена устаревшего ответа: race condition при быстром поиске
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Реализуй fetchWithRetry(url, options, maxRetries)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Дедупликация: не запускай второй identical fetch, пока первый pending
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Retry реализован\n- [ ] Нет race condition в поиске\n- [ ] Pagination работает без дубликатов

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пагинация постов: кнопка «Загрузить ещё» с cursor (id последнего)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Retry: 3 попытки с задержкой 1s, 2s, 4s при сетевой ошибке
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. In-memory cache Map: повторный запрос того же URL — из кэша
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Skeleton UI на время загрузки, контент без layout shift
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 08 day 5: api patterns retry pagination\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Promise utilities

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Movie Catalog

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Помимо базового Promise.all, в JavaScript есть набор утилит для разных сценариев. Promise.allSettled ждёт завершения всех Promise и возвращает массив { status, value/reason } — идеально, когда нужны результаты нескольких независимых API, даже если часть упала. Promise.race отдаёт результат первого завершившегося Promise — удобно для timeout-обёртки. Promise.any возвращает первый успешный, игнорируя reject (если все упали — AggregateError).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Promise.all работает по принципу fail-fast: один reject ломает весь результат. Используй его, когда все данные обязательны (загрузка профиля + настроек одновременно). Promise.allSettled — когда частичный успех допустим (дашборд с виджетами от разных сервисов). Timeout через race: Promise.race([fetch(url), delay(5000).then(() => Promise.reject('timeout'))]).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Необработанный reject (unhandledrejection) — сигнал, что где-то забыли .catch или try/catch. В production повесь глобальный listener window.addEventListener('unhandledrejection', ...) для логирования. for await...of позволяет последовательно обрабатывать асинхронные итерируемые источники без гонки параллельных запросов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель — выбор инструмента под задачу, как в наборе отвёрток: Promise.all — это шуруп, который либо закручен полностью, либо задача провалена целиком (все данные обязательны); Promise.allSettled — гаечный набор, где допустимо закрутить не все гайки (дашборд из независимых виджетов); Promise.race — секундомер, который останавливается по первому событию, будь то успешный ответ или превышение таймаута.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это понимание пригодится при построении дашбордов и агрегирующих экранов на протяжении всего курса: почти любой сложный UI загружает данные из нескольких источников с разной надёжностью, и выбор правильной Promise-утилиты определяет, упадёт ли весь экран из-за одного медленного виджета. Частое заблуждение — использовать Promise.all по умолчанию для всего подряд: если один из пяти виджетов дашборда временно недоступен, весь дашборд из-за Promise.all останется пустым экраном, хотя четыре виджета вполне могли отрендериться.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример timeout: Promise.race([fetch(url), new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), 5000))]) — если fetch не успел за 5 секунд, race вернёт reject от таймера, а не будет ждать вечно зависший запрос. Такой withTimeout — это шаг 2 практики дня, и он же станет частью финального api-wrapper: без таймаута зависший запрос к нестабильному API способен «подвесить» весь пользовательский интерфейс на неопределённое время.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Отдельно стоит запомнить Promise.any: в отличие от race, который отдаёт первый результат вообще (успех или ошибка), any дожидается первого успешного ответа и игнорирует reject, пока не упадут все кандидаты — удобно для запроса к нескольким зеркалам одного API, где важен любой рабочий ответ, а не именно самый быстрый.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Promise.allSettled()\n- MDN: Promise.race()\n- learn.javascript.ru: Promise API

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: выбирай Promise-утилиту по сценарию — all для «всё или ничего», allSettled для «что получилось», race для таймаутов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Загрузи 5 URL через Promise.allSettled, покажи успешные и failed
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Timeout wrapper: withTimeout(promise, 5000) через Promise.race
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Последовательная обработка массива URL без Promise.all (for await)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Глобальный unhandledrejection listener — логирование
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг dashboard недели 7 с новыми паттернами
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сравни Promise.all vs allSettled на массиве с одним failed URL
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь timeout 10s на все fetch в api wrapper
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] allSettled и race использованы по назначению\n- [ ] Timeout на долгие запросы\n- [ ] Нет unhandled promise rejections в Console

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Загрузи 5 URL через Promise.allSettled, покажи успешные и failed
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Timeout wrapper: withTimeout(promise, 5000) через Promise.race
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Последовательная обработка массива URL без Promise.all (for await)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Глобальный unhandledrejection listener — логирование
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 08 day 6: promise utilities timeout\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Асинхронная архитектура

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Movie Catalog

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Асинхронная архитектура приложения определяет, как слои общаются между собой. API-слой возвращает данные или бросает типизированную ошибку (ApiError со статусом) — он не знает о DOM и не решает, показать спиннер или toast. UI-слой подписывается на состояние и рендерит соответствующий экран. Между ними — слой состояния с явными фазами: idle | loading | success | error | empty.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Явная state machine убирает «зависшие» экраны: в каждый момент UI находится ровно в одном состоянии, и переходы предсказуемы (loading → success или loading → error). Простой pub/sub (createAsyncState с subscribe/setState) даёт реактивность без фреймворка — задел на React hooks. При тестировании async-кода fetch можно подменить mock-функцией, возвращающей фиксированный Promise.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        На следующих неделях TypeScript добавит Promise<T> как контракт: async-функция документирует, какой тип данных вернётся. Сейчас зафиксируй принцип: асинхронность — это не только синтаксис, а разделение ответственности между запросом, состоянием и отображением.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель — конвейер на заводе с чёткими станциями: сырьё (запрос) поступает на станцию API, где либо превращается в готовую деталь (данные), либо помечается браком (ApiError) с понятной причиной. Дальше деталь попадает на станцию состояния, которая просто фиксирует текущую фазу конвейера, и только затем — на станцию сборки (UI), которая ничего не решает сама, а лишь отображает то, что сообщила предыдущая станция. Перепутай станции местами (например, дай UI напрямую вызывать fetch и решать, что показывать) — и конвейер быстро превратится в клубок проводов, который невозможно чинить.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это разделение — прямая подготовка к React: useState/useReducer (неделя 11) — это, по сути, официальная реализация той же идеи «явное состояние + подписка на изменения», которую ты сегодня собираешь вручную через createAsyncState. Частое заблуждение начинающих — хранить состояние загрузки как отдельные булевы флаги (isLoading, isError, isEmpty), которые могут противоречить друг другу (например, isLoading = true и isError = true одновременно), вместо одного явного состояния, где такие противоречия структурно невозможны.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пример на практике: функция search(query) в проекте «Каталог фильмов» должна явно переводить состояние idle → loading → success (нашлись фильмы), loading → empty (пустой результат) или loading → error (сеть упала) — и ни один компонент UI не должен сам решать, какой текст показать в каждом случае, кроме как читая это единственное состояние. Это и есть критерий «api / state / ui разделены» из чеклиста дня.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- javascript.info: Промисы\n- patterns.dev: Observer Pattern\n- TypeScript Handbook: Generics — подготовка к неделе 10

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: async-архитектура — это явные состояния UI и чёткие границы между api, state и render.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реализуй хук-подобный паттерн createAsyncState() — subscribe на изменения
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. UI автоматически реагирует на idle/loading/success/error
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Интегрируй в проект «Каталог фильмов» (OMDb или TMDB free tier / mock)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Поиск + детали фильма + избранное в localStorage
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Code review своего async-кода по чеклисту
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Empty state: «Ничего не найдено» при пустом результате поиска
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-08-done на финальном коммите
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Явные состояния async-операций в UI\n- [ ] api / state / ui разделены\n- [ ] Проект работает без ошибок в Console

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реализуй хук-подобный паттерн createAsyncState() — subscribe на изменения
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. UI автоматически реагирует на idle/loading/success/error
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Интегрируй в проект «Каталог фильмов» (OMDb или TMDB free tier / mock)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Поиск + детали фильма + избранное в localStorage
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add ...git commit -m \"week 08 day 7: movie catalog final\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Каталог фильмов — async SPA с поиском, деталями, избранным и robust error handling.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подробное описание: docs/projects.md — Неделя 8

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        API: OMDb (omdbapi.com) или mock JSON server.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:\n- [ ] async/await + api wrapper + retry/timeout\n- [ ] Состояния loading/error/empty/data\n- [ ] Promise.all для параллельной загрузки деталей\n- [ ] Избранное в localStorage, синхронизация с UI\n- [ ] Папка week-08/ с README и скриншотом\n- [ ] Поиск по названию с debounce и отменой устаревших запросов\n- [ ] Карточка фильма: постер, год, рейтинг, описание\n- [ ] Избранное: add/remove, persist, отдельная вкладка или секция\n- [ ] Тег week-08-done на финальном коммите

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Объясни Event Loop на примере setTimeout + Promise?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Разница Promise.all и Promise.allSettled?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Когда await блокирует UI, а когда нет?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что такое CORS и кто его настраивает?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как отменить fetch-запрос?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Movie Catalog** в `learning-log/week-08/`, осмысленная Git-история, тег `week-08-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nAsync/await, HTTP, работа с REST API\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-08-day-1", "label": "День 1 (Mon): Асинхронность и Event Loop"}, {"id": "week-08-day-2", "label": "День 2 (Tue): Promises — основы"}, {"id": "week-08-day-3", "label": "День 3 (Wed): async/await"}, {"id": "week-08-day-4", "label": "День 4 (Thu): HTTP углублённо"}, {"id": "week-08-day-5", "label": "День 5 (Fri): Паттерны работы с API"}, {"id": "week-08-day-6", "label": "День 6 (Sat): Promise utilities"}, {"id": "week-08-day-7", "label": "День 7 (Sun): Асинхронная архитектура"}, {"id": "week-08-project", "label": "Проект недели"}, {"id": "week-08-review", "label": "Ревью-чеклист"}], "text": "Неделя 8: Async JS — promises, event loop, HTTP, API patterns Цель недели: глубоко понять асинхронность в JavaScript, Promises, Event Loop и паттерны работы с API. Литература: Kyle Simpson «You Don't Know JS: Async & Performance», learn.javascript.ru: Промисы , MDN Event Loop , JavaScript.info: Event loop , Philip Roberts: What the heck is the event loop? Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-08/ День 1 (Mon): Асинхронность и Event Loop Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Movie Catalog Теория JavaScript однопоточен: в каждый момент времени выполняется только один фрагмент кода на main thread. Синхронные операци…"} \ No newline at end of file diff --git a/docs/weeks/09.json b/docs/weeks/09.json index e278409..2da3ca1 100644 --- a/docs/weeks/09.json +++ b/docs/weeks/09.json @@ -1 +1 @@ -{"id": "week-09", "title": "JS advanced", "fullTitle": "Неделя 9: JS advanced — closures, prototypes, classes, patterns", "html": "

                                                                                                                                                                                                                        Неделя 9: JS advanced — closures, prototypes, classes, patterns

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: углубить понимание JavaScript — замыкания, прототипы, классы и практические паттерны проектирования.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература: Kyle Simpson «YDKJS: Scope & Closures», «YDKJS: this & Object Prototypes», learn.javascript.ru: Прототипы, patterns.dev, MDN: Closures, javascript.info: Продвинутая работа с функциями

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git: минимум 1 осмысленный коммит каждый день в learning-log/week-09/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Scope и замыкания

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library System

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Область видимости (scope) определяет, где переменная доступна для чтения и записи. В JavaScript действует лексическая (статическая) область: функция «видит» переменные того места, где была объявлена, а не где вызвана. let и const создают блочную область ({ ... }), а устаревший var — функциональную, что приводит к неожиданным утечкам переменных из циклов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Замыкание (closure) возникает, когда внутренняя функция сохраняет доступ к переменным внешней функции даже после того, как внешняя завершила выполнение. Практически это означает: createCounter() возвращает функции increment и getValue, которые «помнят» переменную count в своём лексическом окружении. Замыкания — основа приватности данных без классов: createBankAccount(balance) скрывает баланс от внешнего кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Классическая ловушка — цикл с var и setTimeout: все колбэки ссылаются на одну и ту же переменную i с финальным значением. let в цикле создаёт новую привязку на каждой итерации, решая проблему. Замыкания удерживают ссылки на внешние переменные и могут мешать сборщику мусора — не замыкай на большие объекты без необходимости.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Замыкание\n- MDN: Closures\n- javascript.info: Замыкание

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: замыкание — это функция плюс её лексическое окружение; на этом строятся приватность, фабрики и модульный паттерн.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. createCounter() — increment, decrement, getValue через closure
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Ловушка цикла: for (var i=0; ...) + setTimeout — исправь через let и closure
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. createMultiplier(n) → функция умножения на n
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Приватное поле в factory createBankAccount(balance)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Объясни замыкание вслух за 2 минуты без кода
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Реализуй once(fn) — функция, которая вызывает fn только один раз
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Создай папку learning-log/week-09/ и файл day-01-closures.js с примерами
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Counter работает без глобальных переменных

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Классическая ловушка var+setTimeout исправлена

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Могу объяснить closure своими словами

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. createCounter() — increment, decrement, getValue через closure
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Ловушка цикла: for (var i=0; ...) + setTimeout — исправь через let и closure
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. createMultiplier(n) → функция умножения на n
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Приватное поле в factory createBankAccount(balance)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-09\n\ngit add day-01-closures.js\n\ngit commit -m "week-09 day-01: замыкания, createCounter и once"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Создание функций в цикле с var — все ссылаются на финальный i

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Утечки памяти через closure на большие объекты

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Путаница closure и this

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): this и контекст вызова

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library System

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевое слово this в JavaScript определяется не местом объявления функции, а способом вызова. Существует четыре правила (в порядке приоритета): 1) new binding — this указывает на новый объект; 2) explicit binding — call/apply/bind задают this явно; 3) implicit binding — obj.method() привязывает this к obj; 4) default binding — в strict mode this равен undefined, иначе window.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Потеря контекста — частая ошибка: const fn = obj.handleClick; btn.addEventListener('click', fn) передаёт функцию без объекта, и this внутри станет undefined. Решение — bind: fn.bind(obj) или стрелочная обёртка () => obj.handleClick(). Методы call и apply вызывают функцию немедленно с заданным this; bind возвращает новую функцию с навсегда привязанным контекстом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Стрелочные функции не имеют собственного this — они берут this из окружающего лексического scope. Это удобно для колбэков (map, setTimeout), но делает стрелочные функции плохими методами объектов. В strict mode default binding безопаснее — случайная привязка к window исчезает.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Методы привязки контекста\n- learn.javascript.ru: Справка по оператору this\n- MDN: this

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: this — не переменная, а результат вызова; потеря контекста лечится bind, а стрелочные функции наследуют this снаружи.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Демонстрация 4 правил this — 4 примера в Console
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Исправь button.addEventListener('click', obj.handleClick) через bind
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Заимствование метода: [].slice.call(arguments)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сравни обычную и arrow function как метод объекта
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. partial через bind: const double = multiply.bind(null, 2)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Реализуй call/apply вручную для одного примера — пойми механику
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Запиши конспект «4 правила this» в day-02-this.md
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] bind использован для сохранения контекста

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Понимаю, почему arrow не подходит как метод

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] 4 правила this — конспект

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Демонстрация 4 правил this — 4 примера в Console
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Исправь button.addEventListener('click', obj.handleClick) через bind
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Заимствование метода: [].slice.call(arguments)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сравни обычную и arrow function как метод объекта
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-09\n\ngit add day-02-this.js day-02-this.md\n\ngit commit -m "week-09 day-02: this, bind и 4 правила контекста"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): Прототипы и наследование

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library System

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Наследование в JavaScript реализовано через цепочку прототипов, а не через классы в классическом ООП-смысле. Каждый объект имеет внутреннюю ссылку [[Prototype]] (доступна через Object.getPrototypeOf или устаревшее __proto__). При обращении к свойству движок ищет его на самом объекте, затем на прототипе, затем на прототипе прототипа — до null.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции-конструкторы создают объекты через new: new Person('Anna') создаёт объект, привязывает this и устанавливает [[Prototype]] равным Person.prototype. Методы размещают на prototype, чтобы все экземпляры делили одну функцию, а не копировали её. Object.create(proto) создаёт объект с заданным прототипом без конструктора — чистый способ наследования.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        instanceof проверяет, есть ли Constructor.prototype в цепочке прототипов объекта — это не проверка «типа» в смысле TypeScript. hasOwnProperty отличает собственные свойства от унаследованных. Классы ES6 (class Person) — синтаксический сахар над этой же моделью; typeof Person === 'function'. Никогда не модифицируй Array.prototype или Object.prototype в production — это ломает чужой код.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Прототипное наследование\n- learn.javascript.ru: F.prototype\n- MDN: Object.create()

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: прототипная цепочка — механизм делегирования свойств; class лишь удобная обёртка над ним.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Constructor Person(name) + Person.prototype.greet
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Student наследует Person через Object.create(Person.prototype)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Проверь цепочку: student instanceof Student, instanceof Person
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Добавь метод на Array.prototype — пойми, почему это плохая идея
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Нарисуй prototype chain для своих объектов
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Реализуй inherits(Child, Parent) без class — утилита наследования
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Сравни размер объектов: factory vs constructor — когда что выгоднее
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Наследование без class syntax (хотя бы один пример)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Понимаю разницу proto и prototype

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Не поллю глобальные прототипы в production-коде

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Constructor Person(name) + Person.prototype.greet
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Student наследует Person через Object.create(Person.prototype)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Проверь цепочку: student instanceof Student, instanceof Person
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Добавь метод на Array.prototype — пойми, почему это плохая идея
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-09\n\ngit add day-03-prototypes.js\n\ngit commit -m "week-09 day-03: прототипы, Person/Student и inherits"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): Классы ES6+

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library System

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Синтаксис class в ES6+ делает прототипное наследование читаемым. Класс объявляется как class TodoItem { constructor(title) { ... } toggle() { ... } }. Методы автоматически попадают на prototype. extends связывает прототипы дочернего и родительского классов, а super() в конструкторе вызывает родительский конструктор — без этого this в дочернем классе недоступен.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Статические методы (static fromJSON(obj)) принадлежат самому классу, а не экземплярам — удобны для фабрик и утилит. Геттеры и сеттеры (get isOverdue()) выглядят как свойства, но вычисляются при обращении. С ES2022 приватные поля #id дают настоящую инкапсуляцию: к ним нельзя обратиться снаружи, в отличие от конвенции _id.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Когда выбирать class, а когда factory + closure? Класс хорош для сущностей с общим прототипом и иерархией (Book extends Media). Factory с замыканием — для объектов с приватным состоянием без наследования. Под капотом class всё равно функция с prototypetypeof TodoItem === 'function'.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Класс\n- learn.javascript.ru: Наследование классов\n- MDN: Classes

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: class — это читаемый синтаксис над прототипами; #private и static делают модель данных явной и безопасной.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. class TodoItem { constructor(title) ... toggle() }
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. class TodoList extends Array или композиция — список с методами add/remove
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Static TodoItem.fromJSON(obj) — фабричный метод десериализации
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Private #id в классе — генерация уникального id
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг каталога фильмов: class Movie, MovieCollection
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь геттер isOverdue для задачи с дедлайном
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Напиши unit-проверки вручную (assert) для TodoItem.toggle()
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] extends + super корректны

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Static method для десериализации

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Private field использован

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. class TodoItem { constructor(title) ... toggle() }
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. class TodoList extends Array или композиция — список с методами add/remove
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Static TodoItem.fromJSON(obj) — фабричный метод десериализации
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Private #id в классе — генерация уникального id
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-09\n\ngit add src/models/\n\ngit commit -m "week-09 day-04: классы TodoItem, Movie и private fields"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Паттерны проектирования

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library System

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Паттерны проектирования — проверенные решения типовых задач в архитектуре кода. Observer (Pub-Sub) отделяет источник событий от подписчиков: store вызывает emit('change', data), а UI подписывается через on('change', render). Компоненты не знают друг о друге напрямую — слабая связанность упрощает рефакторинг. EventEmitter на 50 строк — отличная учебная реализация.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Module pattern (в ES modules — через export/import) инкапсулирует детали реализации: наружу видны только публичные функции. Strategy позволяет подменять алгоритм (сортировка byDate / byTitle) без ветвления if/else в клиентском коде — стратегия передаётся как функция. Factory (createNotification('error', msg)) скрывает создание объектов за единым интерфейсом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Singleton гарантирует один экземпляр (например, глобальный store), но усложняет тестирование и создаёт скрытое глобальное состояние — используй осознанно. MVC/MVP разделяют Model (данные), View (DOM) и Controller (логика) — твой Todo уже движется в эту сторону. Главное правило: не применяй паттерн ради паттерна в проекте на 50 строк.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- patterns.dev: Observer Pattern\n- patterns.dev: Module Pattern\n- patterns.dev

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: паттерн оправдан, когда он снижает связанность или упрощает расширение — не когда добавляет абстракцию ради абстракции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. EventEmitter: on, off, emit — 50 строк
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Подпиши UI на изменения store через Observer
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Strategy: сортировка byDate, byTitle — переключаемые функции
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Factory createNotification(type, message) → toast/error/success
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг Todo: Store (state) + View (DOM) + Controller
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь once(event, handler) в EventEmitter
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Задокументируй в README, какие паттерны где применены
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] EventEmitter работает с несколькими подписчиками

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Store отделён от DOM

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Минимум 2 паттерна применены осознанно

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. EventEmitter: on, off, emit — 50 строк
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Подпиши UI на изменения store через Observer
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Strategy: сортировка byDate, byTitle — переключаемые функции
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Factory createNotification(type, message) → toast/error/success
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-09\n\ngit add src/patterns/ src/store.js\n\ngit commit -m "week-09 day-05: EventEmitter, Strategy и Store/View"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Функциональные приёмы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library System

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функциональное программирование в JavaScript — набор приёмов, делающих код предсказуемым. Чистая функция (pure function) при одинаковых аргументах всегда возвращает одинаковый результат и не вызывает побочных эффектов (не мутирует внешние переменные, не пишет в DOM). map, filter, reduce — примеры функций высшего порядка (HOF): они принимают функцию как аргумент и абстрагируют обход коллекции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Композиция объединяет маленькие функции в конвейер: pipe(validate, normalize, save)(input) читается слева направо, compose — справа налево. Каррирование превращает add(a, b) в add(a)(b) — полезно для частичного применения (filterBy('status', 'active')). Иммутабельность достигается через spread и structuredClone вместо прямой мутации.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Рекурсия элегантна для деревьев и вложенных структур, но глубокая рекурсия упрётся в лимит стека (stack overflow). Для горячих путей предпочитай итерацию. memoize(fn) кэширует результаты чистой функции по аргументам — классический приём оптимизации. Referential transparency означает: можно заменить вызов функции её результатом без изменения поведения программы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Каррирование\n- MDN: Array.prototype.reduce()\n- javascript.info: Рекурсия и стек

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: pure functions + immutability + composition дают код, который легко тестировать, переиспользовать и рассуждать о нём.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши обработку списка только pure functions
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. pipe(...fns) — композиция справа налево
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Curried add(a)(b)(c) или практичный filterBy(prop, value)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Рекурсивный обход вложенного меню (tree)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Сравни производительность recursion vs loop для factorial(100) — stack overflow?
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Реализуй memoize(fn) для чистой функции с кэшем
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Рефакторинг фильтрации каталога через pipe из pure-функций
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Минимум 3 pure functions

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] pipe/compose реализован

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Понимаю риск stack overflow в рекурсии

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши обработку списка только pure functions
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. pipe(...fns) — композиция справа налево
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Curried add(a)(b)(c) или практичный filterBy(prop, value)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Рекурсивный обход вложенного меню (tree)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-09\n\ngit add src/utils/fp.js\n\ngit commit -m "week-09 day-06: pipe, currying и memoize"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Рефакторинг и code quality

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library System

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Качество кода определяется не только работоспособностью, но и читаемостью, поддерживаемостью и предсказуемостью. SOLID в JavaScript-практике чаще всего сводится к двум принципам: Single Responsibility (один модуль — одна задача: api.js не рендерит DOM) и Dependency Inversion (высокоуровневый код зависит от абстракций, а не от конкретных реализаций). DRY (Don't Repeat Yourself) полезен, но иногда явное дублирование лучше преждевременной абстракции (правило WET — Write Everything Twice).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        ESLint ловит ошибки до runtime: неиспользуемые переменные, потерянные await, проблемы с ==. Prettier унифицирует форматирование — споры о пробелах исчезают. JSDoc документирует публичный API без TypeScript: @param {string} url, @returns {Promise<User>}. Это мост к строгой типизации на следующей неделе.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        ADR (Architecture Decision Record) — короткий документ «почему выбрали Store + Observer, а не один монолитный файл». Code review checklist: понятные имена, нет скрытых side effects, ошибки обработаны, модули имеют чёткие границы. Подготовка к TypeScript — явные контракты функций через JSDoc или .ts файлы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- JSDoc reference\n- ESLint: Getting Started\n- adr.github.io — формат Architecture Decision Records

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: инструменты (ESLint, JSDoc, ADR) и принципы (SRP, явные контракты) готовят кодовую базу к росту и TypeScript.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи ESLint (eslint:recommended) к проекту
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Исправь все warnings
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Рефакторинг каталога: classes + observer store + api module
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. JSDoc для всех публичных функций api-модуля
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Напиши ADR (Architecture Decision Record) на 1 страницу — почему выбрана структура
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Собери скелет Library System — папки models/, store/, ui/
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Прогони финальный self-review по ревью-чеклисту недели
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] ESLint проходит без ошибок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Архитектура store/view/api

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] JSDoc на ключевых экспортах

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи ESLint (eslint:recommended) к проекту
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Исправь все warnings
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Рефакторинг каталога: classes + observer store + api module
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. JSDoc для всех публичных функций api-модуля
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-09\n\ngit add .\n\ngit commit -m "week-09 day-07: ESLint, ADR и скелет Library System"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Library System — OOP + паттерны на ванильном JS. Подробное ТЗ: docs/projects.md — Неделя 9.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Сущности: Book (title, author, isbn), Member (name, id), Library (выдача/возврат, учёт копий). Observer уведомляет UI об изменениях. Store в localStorage.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          CRUD книг и читателей; выдача и возврат с проверкой доступности

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Поиск по названию/автору; история выдач для члена библиотеки

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          UI: список книг, форма добавления, панель «на руках у читателей»

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Модульная структура ES modules, без глобальных переменных

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Минимум 2 класса с наследованием или композицией (Book / Member / Library)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] EventEmitter/Observer для UI updates при изменении store

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Closure или private fields (#) для инкапсуляции внутреннего состояния

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] ESLint + модульная структура (models/, store/, ui/, patterns/)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Persist в localStorage с миграцией схемы при необходимости

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] README с инструкцией запуска и описанием архитектуры

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тег week-09-done после финальной проверки

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Что такое замыкание и зачем createCounter?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          4 правила определения this?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Разница __proto__ и prototype?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Class vs factory function — когда что?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Могу ли я реализовать простой pub/sub с нуля?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Library System** в `learning-log/week-09/`, осмысленная Git-история, тег `week-09-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nClosures, ООП и паттерны в JavaScript\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-09-day-1", "label": "День 1 (Mon): Scope и замыкания"}, {"id": "week-09-day-2", "label": "День 2 (Tue): this и контекст вызова"}, {"id": "week-09-day-3", "label": "День 3 (Wed): Прототипы и наследование"}, {"id": "week-09-day-4", "label": "День 4 (Thu): Классы ES6+"}, {"id": "week-09-day-5", "label": "День 5 (Fri): Паттерны проектирования"}, {"id": "week-09-day-6", "label": "День 6 (Sat): Функциональные приёмы"}, {"id": "week-09-day-7", "label": "День 7 (Sun): Рефакторинг и code quality"}, {"id": "week-09-project", "label": "Проект недели"}, {"id": "week-09-review", "label": "Ревью-чеклист"}], "text": "Неделя 9: JS advanced — closures, prototypes, classes, patterns Цель недели: углубить понимание JavaScript — замыкания, прототипы, классы и практические паттерны проектирования. Литература: Kyle Simpson «YDKJS: Scope & Closures», «YDKJS: this & Object Prototypes», learn.javascript.ru: Прототипы , patterns.dev , MDN: Closures , javascript.info: Продвинутая работа с функциями Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-09/ День 1 (Mon): Scope и замыкания Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Library System Теория Область видимости (scope) определяет, где переменная доступна для чтения и записи. В JavaScript действует…"} \ No newline at end of file +{"id": "week-09", "title": "JS advanced", "fullTitle": "Неделя 9: JS advanced — closures, prototypes, classes, patterns", "html": "

                                                                                                                                                                                                                        Неделя 9: JS advanced — closures, prototypes, classes, patterns

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: углубить понимание JavaScript — замыкания, прототипы, классы и практические паттерны проектирования.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература: Kyle Simpson «YDKJS: Scope & Closures», «YDKJS: this & Object Prototypes», learn.javascript.ru: Прототипы, patterns.dev, MDN: Closures, javascript.info: Продвинутая работа с функциями

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git: минимум 1 осмысленный коммит каждый день в learning-log/week-09/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Scope и замыкания

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library System

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Область видимости (scope) определяет, где переменная доступна для чтения и записи. В JavaScript действует лексическая (статическая) область: функция «видит» переменные того места, где была объявлена, а не где вызвана. let и const создают блочную область ({ ... }), а устаревший var — функциональную, что приводит к неожиданным утечкам переменных из циклов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Замыкание (closure) возникает, когда внутренняя функция сохраняет доступ к переменным внешней функции даже после того, как внешняя завершила выполнение. Практически это означает: createCounter() возвращает функции increment и getValue, которые «помнят» переменную count в своём лексическом окружении. Замыкания — основа приватности данных без классов: createBankAccount(balance) скрывает баланс от внешнего кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Классическая ловушка — цикл с var и setTimeout: все колбэки ссылаются на одну и ту же переменную i с финальным значением. let в цикле создаёт новую привязку на каждой итерации, решая проблему. Замыкания удерживают ссылки на внешние переменные и могут мешать сборщику мусора — не замыкай на большие объекты без необходимости.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Хорошая мысленная модель замыкания — рюкзак, который функция берёт с собой при рождении и никогда не снимает: внутри рюкзака лежат все переменные из окружения, где функция была объявлена. Даже если внешняя функция давно завершилась и, казалось бы, её данные должны исчезнуть, рюкзак продолжает их держать, пока жива хотя бы одна функция, которая на них ссылается — поэтому getValue() из createCounter() спустя сколько угодно вызовов «помнит» актуальное значение count.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Замыкания — это не просто приём для счётчиков: это основа модульного паттерна (день 5 этой недели), React-хуков (useState работает благодаря замыканиям внутри функционального компонента) и мемоизации (memoize(fn), день 6). Без понимания замыканий последующие темы курса будут восприниматься как магия, а не как логичное следствие лексической области видимости.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — путать замыкание с копированием значения: createMultiplier(n) не сохраняет копию n в момент вызова функции-результата, а держит живую ссылку на переменную n в её лексическом окружении. Классический пример — цикл for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 100) } выведет 3, 3, 3, потому что все три колбэка держат один и тот же рюкзак с переменной i, которая к моменту вызова уже равна 3. Замена var на let создаёт отдельный рюкзак (и отдельную переменную i) для каждой итерации — колбэки выведут 0, 1, 2. Это задание 2 практики дня, и оно — лучший способ прочувствовать разницу на собственном опыте, а не поверить на слово.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Замыкание\n- MDN: Closures\n- javascript.info: Замыкание

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: замыкание — это функция плюс её лексическое окружение; на этом строятся приватность, фабрики и модульный паттерн.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. createCounter() — increment, decrement, getValue через closure
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Ловушка цикла: for (var i=0; ...) + setTimeout — исправь через let и closure
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. createMultiplier(n) → функция умножения на n
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Приватное поле в factory createBankAccount(balance)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Объясни замыкание вслух за 2 минуты без кода
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Реализуй once(fn) — функция, которая вызывает fn только один раз
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Создай папку learning-log/week-09/ и файл day-01-closures.js с примерами
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Counter работает без глобальных переменных

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Классическая ловушка var+setTimeout исправлена

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Могу объяснить closure своими словами

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. createCounter() — increment, decrement, getValue через closure
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Ловушка цикла: for (var i=0; ...) + setTimeout — исправь через let и closure
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. createMultiplier(n) → функция умножения на n
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Приватное поле в factory createBankAccount(balance)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-09\n\ngit add day-01-closures.js\n\ngit commit -m "week-09 day-01: замыкания, createCounter и once"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Создание функций в цикле с var — все ссылаются на финальный i

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Утечки памяти через closure на большие объекты

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Путаница closure и this

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): this и контекст вызова

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library System

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевое слово this в JavaScript определяется не местом объявления функции, а способом вызова. Существует четыре правила (в порядке приоритета): 1) new binding — this указывает на новый объект; 2) explicit binding — call/apply/bind задают this явно; 3) implicit binding — obj.method() привязывает this к obj; 4) default binding — в strict mode this равен undefined, иначе window.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Потеря контекста — частая ошибка: const fn = obj.handleClick; btn.addEventListener('click', fn) передаёт функцию без объекта, и this внутри станет undefined. Решение — bind: fn.bind(obj) или стрелочная обёртка () => obj.handleClick(). Методы call и apply вызывают функцию немедленно с заданным this; bind возвращает новую функцию с навсегда привязанным контекстом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Стрелочные функции не имеют собственного this — они берут this из окружающего лексического scope. Это удобно для колбэков (map, setTimeout), но делает стрелочные функции плохими методами объектов. В strict mode default binding безопаснее — случайная привязка к window исчезает.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Удобная мысленная модель — бейдж сотрудника, а не имя, зашитое в паспорт: this — это не свойство самой функции, а бейдж, который функция получает в момент вызова в зависимости от того, как её позвали. Одна и та же функция greet даст разный this, если её вызвать как user.greet() (бейдж «user»), через greet.call(otherUser) (бейдж «otherUser») или просто greet() без объекта (бейдж не выдан — undefined в strict mode).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Понимание this критично для следующих двух дней недели: прототипы и классы (class и extends) целиком построены на корректной передаче this через цепочку конструкторов, а super() внутри дочернего класса — по сути явная передача бейджа от родителя к потомку. Позже, при работе с обработчиками событий DOM, потеря this — одна из самых частых причин багов уровня «функция вызвалась, но упала с Cannot read property of undefined».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что this определяется тем, где объявлена функция (как в замыканиях). На самом деле место объявления не влияет на this вообще — только способ вызова. Пример: const handleClick = obj.handleClick; button.addEventListener('click', handleClick) — внутри handleClick при клике this будет указывать на сам button (implicit binding через слушателя события), а не на obj, как ожидал бы новичок, глядя на исходное место объявления метода. Именно это несоответствие ожиданий — суть задания 2 практики: исправить потерю контекста через bind.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Методы привязки контекста\n- learn.javascript.ru: Справка по оператору this\n- MDN: this

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: this — не переменная, а результат вызова; потеря контекста лечится bind, а стрелочные функции наследуют this снаружи.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Демонстрация 4 правил this — 4 примера в Console
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Исправь button.addEventListener('click', obj.handleClick) через bind
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Заимствование метода: [].slice.call(arguments)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сравни обычную и arrow function как метод объекта
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. partial через bind: const double = multiply.bind(null, 2)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Реализуй call/apply вручную для одного примера — пойми механику
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Запиши конспект «4 правила this» в day-02-this.md
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] bind использован для сохранения контекста

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Понимаю, почему arrow не подходит как метод

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] 4 правила this — конспект

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Демонстрация 4 правил this — 4 примера в Console
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Исправь button.addEventListener('click', obj.handleClick) через bind
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Заимствование метода: [].slice.call(arguments)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сравни обычную и arrow function как метод объекта
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-09\n\ngit add day-02-this.js day-02-this.md\n\ngit commit -m "week-09 day-02: this, bind и 4 правила контекста"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): Прототипы и наследование

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library System

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Наследование в JavaScript реализовано через цепочку прототипов, а не через классы в классическом ООП-смысле. Каждый объект имеет внутреннюю ссылку [[Prototype]] (доступна через Object.getPrototypeOf или устаревшее __proto__). При обращении к свойству движок ищет его на самом объекте, затем на прототипе, затем на прототипе прототипа — до null.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции-конструкторы создают объекты через new: new Person('Anna') создаёт объект, привязывает this и устанавливает [[Prototype]] равным Person.prototype. Методы размещают на prototype, чтобы все экземпляры делили одну функцию, а не копировали её. Object.create(proto) создаёт объект с заданным прототипом без конструктора — чистый способ наследования.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        instanceof проверяет, есть ли Constructor.prototype в цепочке прототипов объекта — это не проверка «типа» в смысле TypeScript. hasOwnProperty отличает собственные свойства от унаследованных. Классы ES6 (class Person) — синтаксический сахар над этой же моделью; typeof Person === 'function'. Никогда не модифицируй Array.prototype или Object.prototype в production — это ломает чужой код.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель прототипной цепочки — библиотека с этажами: если нужной книги (свойства) нет на твоей полке (собственный объект), библиотекарь поднимается на этаж выше (прототип) и ищет там, потом ещё выше, и так до последнего этажа (Object.prototype), после которого выше уже ничего нет (null). Поиск свойства в JavaScript устроен именно так — не копированием данных между объектами, а делегированием запроса вверх по цепочке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эта модель объясняет, почему методы размещают на prototype, а не создают заново в каждом экземпляре: 1000 объектов Person не хранят 1000 копий функции greet — все они делегируют вызов одному и тому же методу на Person.prototype, экономя память. Понимание прототипов готовит к завтрашним классам ES6 (class — это просто удобный синтаксис поверх той же модели) и объясняет, почему typeof MyClass === 'function' — классы в JS остаются функциями под капотом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что instanceof проверяет «настоящий тип» объекта, как в строго типизированных языках: на самом деле obj instanceof Person лишь проверяет, встречается ли Person.prototype где-то в цепочке прототипов obj, и это можно подделать через Object.create. Конкретный пример из практики дня: Student, созданный через Object.create(Person.prototype), пройдёт проверку student instanceof Person, даже если ты никогда явно не писал «Student наследует Person» — прототипная цепочка это единственный источник истины, а не namespace или декларация типа.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Прототипное наследование\n- learn.javascript.ru: F.prototype\n- MDN: Object.create()

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: прототипная цепочка — механизм делегирования свойств; class лишь удобная обёртка над ним.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Constructor Person(name) + Person.prototype.greet
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Student наследует Person через Object.create(Person.prototype)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Проверь цепочку: student instanceof Student, instanceof Person
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Добавь метод на Array.prototype — пойми, почему это плохая идея
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Нарисуй prototype chain для своих объектов
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Реализуй inherits(Child, Parent) без class — утилита наследования
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Сравни размер объектов: factory vs constructor — когда что выгоднее
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Наследование без class syntax (хотя бы один пример)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Понимаю разницу proto и prototype

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Не поллю глобальные прототипы в production-коде

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Constructor Person(name) + Person.prototype.greet
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Student наследует Person через Object.create(Person.prototype)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Проверь цепочку: student instanceof Student, instanceof Person
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Добавь метод на Array.prototype — пойми, почему это плохая идея
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-09\n\ngit add day-03-prototypes.js\n\ngit commit -m "week-09 day-03: прототипы, Person/Student и inherits"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): Классы ES6+

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library System

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Синтаксис class в ES6+ делает прототипное наследование читаемым. Класс объявляется как class TodoItem { constructor(title) { ... } toggle() { ... } }. Методы автоматически попадают на prototype. extends связывает прототипы дочернего и родительского классов, а super() в конструкторе вызывает родительский конструктор — без этого this в дочернем классе недоступен.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Статические методы (static fromJSON(obj)) принадлежат самому классу, а не экземплярам — удобны для фабрик и утилит. Геттеры и сеттеры (get isOverdue()) выглядят как свойства, но вычисляются при обращении. С ES2022 приватные поля #id дают настоящую инкапсуляцию: к ним нельзя обратиться снаружи, в отличие от конвенции _id.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Когда выбирать class, а когда factory + closure? Класс хорош для сущностей с общим прототипом и иерархией (Book extends Media). Factory с замыканием — для объектов с приватным состоянием без наследования. Под капотом class всё равно функция с prototypetypeof TodoItem === 'function'.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель — класс это чертёж (blueprint), а объект — конкретное здание, построенное по этому чертежу: чертёж описывает, какие комнаты (свойства) и какие двери (методы) будут в каждом здании, но жить в самом чертеже нельзя — нужно создать экземпляр через new. extends — это чертёж, который берёт за основу другой чертёж и добавляет к нему этаж, а super() — обязательный вызов «построй сначала базовый этаж по родительскому чертежу», без которого верхний этаж не может опираться ни на что.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Классы становятся рабочим инструментом для всего оставшегося курса: домены проекта «Библиотека» (Book, Member, Library) и, позже, доменные модели в TypeScript и React будут использовать либо классы, либо похожие по духу объектно-ориентированные структуры данных. Приватные поля #id — это первый шаг к пониманию инкапсуляции, который в TypeScript (неделя 10) получит ещё более строгую форму через модификаторы доступа.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать конвенцию _id (подчёркивание) настоящей приватностью: это лишь договорённость между разработчиками, и снаружи класса obj._id прекрасно читается и перезаписывается. Приватное поле #id, в отличие от этого, физически недоступно снаружи — попытка обратиться к obj.#id вне класса вызовет SyntaxError уже на этапе разбора кода, а не просто «плохой тон». Задание 4 практики («Private #id в классе») — шанс почувствовать разницу между «не трогай, пожалуйста» и «невозможно тронуть».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Класс\n- learn.javascript.ru: Наследование классов\n- MDN: Classes

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: class — это читаемый синтаксис над прототипами; #private и static делают модель данных явной и безопасной.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. class TodoItem { constructor(title) ... toggle() }
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. class TodoList extends Array или композиция — список с методами add/remove
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Static TodoItem.fromJSON(obj) — фабричный метод десериализации
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Private #id в классе — генерация уникального id
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг каталога фильмов: class Movie, MovieCollection
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь геттер isOverdue для задачи с дедлайном
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Напиши unit-проверки вручную (assert) для TodoItem.toggle()
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] extends + super корректны

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Static method для десериализации

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Private field использован

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. class TodoItem { constructor(title) ... toggle() }
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. class TodoList extends Array или композиция — список с методами add/remove
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Static TodoItem.fromJSON(obj) — фабричный метод десериализации
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Private #id в классе — генерация уникального id
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-09\n\ngit add src/models/\n\ngit commit -m "week-09 day-04: классы TodoItem, Movie и private fields"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Паттерны проектирования

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library System

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Паттерны проектирования — проверенные решения типовых задач в архитектуре кода. Observer (Pub-Sub) отделяет источник событий от подписчиков: store вызывает emit('change', data), а UI подписывается через on('change', render). Компоненты не знают друг о друге напрямую — слабая связанность упрощает рефакторинг. EventEmitter на 50 строк — отличная учебная реализация.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Module pattern (в ES modules — через export/import) инкапсулирует детали реализации: наружу видны только публичные функции. Strategy позволяет подменять алгоритм (сортировка byDate / byTitle) без ветвления if/else в клиентском коде — стратегия передаётся как функция. Factory (createNotification('error', msg)) скрывает создание объектов за единым интерфейсом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Singleton гарантирует один экземпляр (например, глобальный store), но усложняет тестирование и создаёт скрытое глобальное состояние — используй осознанно. MVC/MVP разделяют Model (данные), View (DOM) и Controller (логика) — твой Todo уже движется в эту сторону. Главное правило: не применяй паттерн ради паттерна в проекте на 50 строк.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель Observer — подписка на рассылку новостей: издатель (store) не знает лично каждого подписчика, он просто публикует событие в общий канал, а все, кто подписан, получают уведомление и решают сами, что с ним делать. Это радикально отличается от прямого вызова updateUI() внутри store — при таком подходе store пришлось бы знать обо всех частях UI, которые на него завязаны, и любое изменение интерфейса требовало бы правки store.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Наблюдатель, который ты реализуешь сегодня вручную (EventEmitter на 50 строк), — тот же принцип, что лежит в основе React: изменение state вызывает ререндер подписанных компонентов, а не императивный вызов render() из логики данных. Понимание паттернов на этом уровне избавляет от ощущения «магии» при первой встрече с useState и useEffect на неделе 11.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — начинать проектирование с вопроса «какой паттерн тут применить», а не «какая проблема связанности у меня есть». Паттерн — это название для решения, которое уже интуитивно напрашивается, а не чек-лист для внедрения ради резюме. Конкретный пример: если Store и View общаются напрямую через прямые вызовы методов друг друга, замена View (например, консольный вывод вместо DOM) потребует переписать Store — а с Observer Store продолжит работать без единой правки, просто у него появится другой подписчик. Это и есть цель задания 5 — «Рефакторинг Todo: Store + View + Controller», где связанность должна снизиться измеримо.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- patterns.dev: Observer Pattern\n- patterns.dev: Module Pattern\n- patterns.dev

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: паттерн оправдан, когда он снижает связанность или упрощает расширение — не когда добавляет абстракцию ради абстракции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. EventEmitter: on, off, emit — 50 строк
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Подпиши UI на изменения store через Observer
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Strategy: сортировка byDate, byTitle — переключаемые функции
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Factory createNotification(type, message) → toast/error/success
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг Todo: Store (state) + View (DOM) + Controller
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь once(event, handler) в EventEmitter
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Задокументируй в README, какие паттерны где применены
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] EventEmitter работает с несколькими подписчиками

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Store отделён от DOM

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Минимум 2 паттерна применены осознанно

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. EventEmitter: on, off, emit — 50 строк
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Подпиши UI на изменения store через Observer
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Strategy: сортировка byDate, byTitle — переключаемые функции
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Factory createNotification(type, message) → toast/error/success
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-09\n\ngit add src/patterns/ src/store.js\n\ngit commit -m "week-09 day-05: EventEmitter, Strategy и Store/View"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Функциональные приёмы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library System

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функциональное программирование в JavaScript — набор приёмов, делающих код предсказуемым. Чистая функция (pure function) при одинаковых аргументах всегда возвращает одинаковый результат и не вызывает побочных эффектов (не мутирует внешние переменные, не пишет в DOM). map, filter, reduce — примеры функций высшего порядка (HOF): они принимают функцию как аргумент и абстрагируют обход коллекции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Композиция объединяет маленькие функции в конвейер: pipe(validate, normalize, save)(input) читается слева направо, compose — справа налево. Каррирование превращает add(a, b) в add(a)(b) — полезно для частичного применения (filterBy('status', 'active')). Иммутабельность достигается через spread и structuredClone вместо прямой мутации.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Рекурсия элегантна для деревьев и вложенных структур, но глубокая рекурсия упрётся в лимит стека (stack overflow). Для горячих путей предпочитай итерацию. memoize(fn) кэширует результаты чистой функции по аргументам — классический приём оптимизации. Referential transparency означает: можно заменить вызов функции её результатом без изменения поведения программы.

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Композиция (pipe/compose) и иммутабельность станут ежедневной практикой в React: обновление state через setState(prev => ({...prev, field: value})) — это иммутабельный апдейт, а селекторы данных обычно строятся именно как композиция маленьких чистых функций. Понимание рекурсии готовит к работе с деревьями — DOM-деревом, деревом компонентов React, вложенными комментариями или категориями.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать, что map/filter мутируют исходный массив: на самом деле оба метода возвращают новый массив, оставляя оригинал нетронутым — в отличие от push, splice или прямого присваивания по индексу, которые мутируют исходные данные. Конкретный пример риска рекурсии — глубоко вложенное дерево комментариев на 10000 уровней: рекурсивный обход упадёт с RangeError: Maximum call stack size exceeded, тогда как итеративный вариант со своим стеком (массивом) отработает без проблем — это стоит проверить в задании 5 практики на factorial(100) и увидеть реальный предел.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тай-брейк между чистотой и производительностью решается прагматично: если функция вызывается редко (обработчик клика), пиши максимально чистой; если в горячем цикле рендера тысяч элементов — допустима контролируемая мутация локальной копии внутри функции, при условии что наружу она всё равно отдаёт новый объект и не трогает входные аргументы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- learn.javascript.ru: Каррирование\n- MDN: Array.prototype.reduce()\n- javascript.info: Рекурсия и стек

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: pure functions + immutability + composition дают код, который легко тестировать, переиспользовать и рассуждать о нём.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши обработку списка только pure functions
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. pipe(...fns) — композиция справа налево
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Curried add(a)(b)(c) или практичный filterBy(prop, value)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Рекурсивный обход вложенного меню (tree)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Сравни производительность recursion vs loop для factorial(100) — stack overflow?
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Реализуй memoize(fn) для чистой функции с кэшем
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Рефакторинг фильтрации каталога через pipe из pure-функций
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Минимум 3 pure functions

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] pipe/compose реализован

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Понимаю риск stack overflow в рекурсии

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши обработку списка только pure functions
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. pipe(...fns) — композиция справа налево
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Curried add(a)(b)(c) или практичный filterBy(prop, value)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Рекурсивный обход вложенного меню (tree)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-09\n\ngit add src/utils/fp.js\n\ngit commit -m "week-09 day-06: pipe, currying и memoize"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Рефакторинг и code quality

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library System

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Качество кода определяется не только работоспособностью, но и читаемостью, поддерживаемостью и предсказуемостью. SOLID в JavaScript-практике чаще всего сводится к двум принципам: Single Responsibility (один модуль — одна задача: api.js не рендерит DOM) и Dependency Inversion (высокоуровневый код зависит от абстракций, а не от конкретных реализаций). DRY (Don't Repeat Yourself) полезен, но иногда явное дублирование лучше преждевременной абстракции (правило WET — Write Everything Twice).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        ESLint ловит ошибки до runtime: неиспользуемые переменные, потерянные await, проблемы с ==. Prettier унифицирует форматирование — споры о пробелах исчезают. JSDoc документирует публичный API без TypeScript: @param {string} url, @returns {Promise<User>}. Это мост к строгой типизации на следующей неделе.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        ADR (Architecture Decision Record) — короткий документ «почему выбрали Store + Observer, а не один монолитный файл». Code review checklist: понятные имена, нет скрытых side effects, ошибки обработаны, модули имеют чёткие границы. Подготовка к TypeScript — явные контракты функций через JSDoc или .ts файлы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель качества кода — не «идеальный» код с первой попытки, а сад, который регулярно пропалывают: рефакторинг — не разовое событие перед дедлайном, а постоянная практика вычищения дублирования, неясных имён и скрытых побочных эффектов по мере роста кодовой базы. Инструменты вроде ESLint и Prettier автоматизируют часть этой прополки, освобождая внимание для более важных архитектурных решений.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Привычка писать явные контракты (через JSDoc сегодня, через TypeScript — уже на следующей неделе) — прямая подготовка к строгой типизации: @param {string} url и @returns {Promise<User>} в JSDoc почти дословно превратятся в сигнатуру function fetchUser(url: string): Promise<User> в TypeScript. Тот, кто честно документирует функции сейчас, столкнётся с TypeScript не как с новым языком, а как с формализацией того, что он и так уже держал в голове.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — воспринимать DRY как абсолютное правило «никогда не повторяй код»: две функции, которые сейчас выглядят одинаково, но описывают разные бизнес-смыслы (например, валидация email пользователя и валидация email в форме подписки на рассылку), могут начать расходиться по мере развития продукта — преждевременное объединение их в одну общую функцию создаст ненужную связанность. Правило WET («write everything twice») напоминает: дай коду повториться два раза, и только на третьем повторении абстрагируй — это здравый компромисс, который стоит внести в ADR из задания 5 практики дня.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- JSDoc reference\n- ESLint: Getting Started\n- adr.github.io — формат Architecture Decision Records

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: инструменты (ESLint, JSDoc, ADR) и принципы (SRP, явные контракты) готовят кодовую базу к росту и TypeScript.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи ESLint (eslint:recommended) к проекту
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Исправь все warnings
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Рефакторинг каталога: classes + observer store + api module
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. JSDoc для всех публичных функций api-модуля
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Напиши ADR (Architecture Decision Record) на 1 страницу — почему выбрана структура
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Собери скелет Library System — папки models/, store/, ui/
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Прогони финальный self-review по ревью-чеклисту недели
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] ESLint проходит без ошибок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Архитектура store/view/api

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] JSDoc на ключевых экспортах

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи ESLint (eslint:recommended) к проекту
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Исправь все warnings
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Рефакторинг каталога: classes + observer store + api module
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. JSDoc для всех публичных функций api-модуля
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-09\n\ngit add .\n\ngit commit -m "week-09 day-07: ESLint, ADR и скелет Library System"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Library System — OOP + паттерны на ванильном JS. Подробное ТЗ: docs/projects.md — Неделя 9.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Сущности: Book (title, author, isbn), Member (name, id), Library (выдача/возврат, учёт копий). Observer уведомляет UI об изменениях. Store в localStorage.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          CRUD книг и читателей; выдача и возврат с проверкой доступности

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Поиск по названию/автору; история выдач для члена библиотеки

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          UI: список книг, форма добавления, панель «на руках у читателей»

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Модульная структура ES modules, без глобальных переменных

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Минимум 2 класса с наследованием или композицией (Book / Member / Library)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] EventEmitter/Observer для UI updates при изменении store

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Closure или private fields (#) для инкапсуляции внутреннего состояния

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] ESLint + модульная структура (models/, store/, ui/, patterns/)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Persist в localStorage с миграцией схемы при необходимости

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] README с инструкцией запуска и описанием архитектуры

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тег week-09-done после финальной проверки

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Что такое замыкание и зачем createCounter?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          4 правила определения this?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Разница __proto__ и prototype?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Class vs factory function — когда что?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Могу ли я реализовать простой pub/sub с нуля?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Library System** в `learning-log/week-09/`, осмысленная Git-история, тег `week-09-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nClosures, ООП и паттерны в JavaScript\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-09-day-1", "label": "День 1 (Mon): Scope и замыкания"}, {"id": "week-09-day-2", "label": "День 2 (Tue): this и контекст вызова"}, {"id": "week-09-day-3", "label": "День 3 (Wed): Прототипы и наследование"}, {"id": "week-09-day-4", "label": "День 4 (Thu): Классы ES6+"}, {"id": "week-09-day-5", "label": "День 5 (Fri): Паттерны проектирования"}, {"id": "week-09-day-6", "label": "День 6 (Sat): Функциональные приёмы"}, {"id": "week-09-day-7", "label": "День 7 (Sun): Рефакторинг и code quality"}, {"id": "week-09-project", "label": "Проект недели"}, {"id": "week-09-review", "label": "Ревью-чеклист"}], "text": "Неделя 9: JS advanced — closures, prototypes, classes, patterns Цель недели: углубить понимание JavaScript — замыкания, прототипы, классы и практические паттерны проектирования. Литература: Kyle Simpson «YDKJS: Scope & Closures», «YDKJS: this & Object Prototypes», learn.javascript.ru: Прототипы , patterns.dev , MDN: Closures , javascript.info: Продвинутая работа с функциями Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-09/ День 1 (Mon): Scope и замыкания Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Library System Теория Область видимости (scope) определяет, где переменная доступна для чтения и записи. В JavaScript действует…"} \ No newline at end of file diff --git a/docs/weeks/10.json b/docs/weeks/10.json index 059b2cf..83b3948 100644 --- a/docs/weeks/10.json +++ b/docs/weeks/10.json @@ -1 +1 @@ -{"id": "week-10", "title": "TypeScript", "fullTitle": "Неделя 10: TypeScript — типы, interfaces, generics basics, TS+React setup", "html": "

                                                                                                                                                                                                                        Неделя 10: TypeScript — типы, interfaces, generics basics, TS+React setup

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: освоить основы TypeScript и подготовить проект к React с типизированной кодовой базой.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература: TypeScript Handbook, learn.javascript.ru: Типы, React TypeScript Cheatsheet, Total TypeScript — Beginners, TSConfig Reference

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git: минимум 1 осмысленный коммит каждый день в learning-log/week-10/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Введение в TypeScript

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Typed API Client

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        TypeScript — это надмножество JavaScript со статической системой типов. Код пишется в .ts (или .tsx для JSX), компилируется компилятором tsc в обычный JavaScript, который выполняется в браузере или Node.js. Типы существуют только на этапе разработки и стираются при компиляции — в runtime никакой проверки типов нет. Зато IDE и компилятор ловят ошибки до запуска: опечатки в свойствах, неверные аргументы, забытые null.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Установка: npm init -y, npm i -D typescript, npx tsc --init создаёт tsconfig.json. Ключевые опции: strict: true (включает все строгие проверки), target (версия JS на выходе), module (система модулей), outDir и rootDir. Базовые типы: string, number, boolean, null, undefined, bigint, symbol. Аннотация явная: let name: string = 'Anna', но чаще полагайся на вывод типов (inference): const count = 0 → TypeScript сам определит number.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Команда npx tsc --noEmit проверяет типы без генерации файлов — удобно в CI. Разница .ts и .tsx: JSX-синтаксис допустим только в .tsx. Скрипт \"build\": \"tsc\" в package.json автоматизирует компиляцию, \"dev\": \"tsc --watch\" пересобирает при каждом сохранении.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- TypeScript: Getting Started\n- learn.javascript.ru: Типы\n- TSConfig Reference

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: TypeScript ловит целый класс ошибок на этапе компиляции — типы это документация, которую нельзя проигнорировать.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай проект learning-log/week-10, инициализируй TypeScript
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перепиши utils.js из прошлых недель в utils.ts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Включи strict: true в tsconfig.json
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Исправь все ошибки компиляции
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Настрой скрипт \"build\": \"tsc\" в package.json
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь \"dev\": \"tsc --watch\" для автопересборки
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Создай src/index.ts — точка входа, импорт utils
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] tsc компилирует без ошибок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] strict: true включён

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Понимаю разницу .ts и .js на выходе

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай проект learning-log/week-10, инициализируй TypeScript
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перепиши utils.js из прошлых недель в utils.ts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Включи strict: true в tsconfig.json
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Исправь все ошибки компиляции
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-10\n\ngit add package.json tsconfig.json src/\n\ngit commit -m "week-10 day-01: инициализация TS-проекта и utils.ts"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Типы, union, literal, any

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Typed API Client

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Union types объединяют несколько типов: string | number означает «или строка, или число». Literal types сужают множество до конкретных значений: type Theme = 'light' | 'dark' — не любая строка, а ровно два варианта. TypeScript не даст присвоить 'blue', если тип допускает только 'light' | 'dark'. Это основа для моделирования состояний и флагов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        any отключает проверку типов — «дыра» в системе, через которую ошибки просачиваются обратно в runtime. Избегай any; вместо него используй unknown — тип «что-то есть, но мы не знаем что». С unknown нельзя ничего делать, пока не сузишь тип через typeof, in или type guard. Discriminated union добавляет общее поле-дискриминатор: { ok: true, data: T } | { ok: false, error: string } — switch по ok сужает тип в каждой ветке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        as const делает объект readonly с literal-типами: const STATUS = { LOADING: 'loading' } as const. Тип never означает «недостижимо» — полезен в exhaustive switch: если добавишь новый вариант union, компилятор укажет на непокрытую ветку. Пользовательские type guards: function isUser(x: unknown): x is User — явный контракт сужения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Handbook: Everyday Types\n- Handbook: Narrowing\n- Total TypeScript: Beginners

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: union + narrowing превращают TypeScript в инструмент моделирования состояний; unknown безопаснее any.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Тип Theme = 'light' | 'dark' для переключателя темы
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Функция formatId(id: string | number): string с narrowing
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Замени any на unknown + проверку перед использованием
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Discriminated union Result = { ok: true, data: T } | { ok: false, error: string }
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Используй as const для объекта констант STATUS
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Напиши type guard isApiError(err): err is ApiError
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Exhaustive switch по union — default: const _exhaustive: never = value
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет any в новом коде

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Union types с корректным narrowing

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Result pattern для ошибок API

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Тип Theme = 'light' | 'dark' для переключателя темы
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Функция formatId(id: string | number): string с narrowing
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Замени any на unknown + проверку перед использованием
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Discriminated union Result = { ok: true, data: T } | { ok: false, error: string }
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-10\n\ngit add src/types/\n\ngit commit -m "week-10 day-02: union, Result pattern и type guards"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          any распространяется как зараза — теряется смысл TS

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Утверждение as Type без проверки — ложная безопасность

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Забытый strictNullChecks — null не ловится

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): Interfaces и type aliases

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Typed API Client

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Объекты в TypeScript описываются через interface или type. interface User { id: number; name: string; email?: string }email? опционален, его может не быть. readonly id: number запрещает переприсвоение после создания. Оба способа описывают форму объекта; различия тонкие: interface можно расширять (extends) и объединять (declaration merging), type гибче для union и mapped types.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Расширение: interface Admin extends User { role: string } добавляет поля. Альтернатива — intersection: type Admin = User & { role: string }. Index signature [key: string]: string описывает объекты с динамическими ключами (словари, кэши). Для объектов предпочитай interface, для union и вычисляемых типов — type.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Utility types из коробки: Readonly<T> делает все поля readonly, ReadonlyArray<T> — неизменяемый массив. В проекте заведи папку types/ с DTO (Data Transfer Objects): Todo, ApiResponse<T>, PaginationMeta. Типизированный api-модуль возвращает Promise<ApiResponse<Todo[]>> вместо «что-то пришло с сервера». Это контракт между слоями, который компилятор проверяет.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Handbook: Objects\n- Handbook: Utility Types\n- React TypeScript Cheatsheet

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: interface/type — это контракт формы данных; DTO в отдельных файлах делают API и доменную модель явными.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Интерфейсы Todo, TodoFilter, TodoState для Todo App
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. interface ApiResponse<T> { data: T; meta: PaginationMeta }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Type alias для функции: type EventHandler = (e: Event) => void
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Расширь UserAdmin с полем permissions: string[]
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг api-модуля с типизированными ответами
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай types/api.ts — все DTO в одном месте
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь readonly к id в Todo — попробуй изменить и поймай ошибку TS
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Все доменные сущности типизированы

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] interface vs type — осознанный выбор

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Опциональные и readonly поля использованы

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Интерфейсы Todo, TodoFilter, TodoState для Todo App
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. interface ApiResponse<T> { data: T; meta: PaginationMeta }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Type alias для функции: type EventHandler = (e: Event) => void
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Расширь UserAdmin с полем permissions: string[]
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-10\n\ngit add src/types/ src/api/\n\ngit commit -m "week-10 day-03: интерфейсы Todo и ApiResponse"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): Generics — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Typed API Client

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Generics (обобщения) позволяют писать функции и типы, работающие с разными типами, сохраняя связь между входом и выходом. function identity<T>(arg: T): T — тип возвращаемого значения совпадает с типом аргумента. Без generics пришлось бы писать отдельные функции для string, number, User или откатываться к any.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Constraints ограничивают generic сверху: <T extends { id: number }> гарантирует, что у T есть поле id. keyof T даёт union всех ключей объекта, а indexed access T[K] — тип значения по ключу. Это основа для pluck(obj, 'name') с правильным return type. Generic defaults <T = string> задают тип по умолчанию, если параметр не указан.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практические применения: async function fetchJson<T>(url: string): Promise<T> типизирует ответ API; getItem<T>(key: string): T | null типизирует localStorage wrapper; groupBy<T, K extends string>(items, keyFn) группирует массив любых объектов. IDE будет подсказывать поля на результате fetchJson<User[]>(url) без ручных кастов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Handbook: Generics\n- Handbook: Keyof Types\n- Total TypeScript: Beginners

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: generics связывают типы входа и выхода — fetchJson<User> безопаснее fetchJson<any>.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. function first<T>(arr: T[]): T | undefined
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. async function fetchJson<T>(url: string): Promise<T> — типизированный fetch
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. function groupBy<T, K extends string>(items: T[], key: (item: T) => K)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Типизируй localStorage wrapper: getItem<T>(key): T | null
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Примени generics в api-клиенте каталога фильмов
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. function pluck<T, K extends keyof T>(obj: T, key: K): T[K]
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Напиши тестовые вызовы с разными T — проверь inference в IDE
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] fetchJson типизирует ответ API

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] groupBy работает с разными типами

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Constraints использован хотя бы раз

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. function first<T>(arr: T[]): T | undefined
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. async function fetchJson<T>(url: string): Promise<T> — типизированный fetch
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. function groupBy<T, K extends string>(items: T[], key: (item: T) => K)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Типизируй localStorage wrapper: getItem<T>(key): T | null
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-10\n\ngit add src/lib/fetch.ts src/lib/storage.ts\n\ngit commit -m "week-10 day-04: generic fetchJson и localStorage wrapper"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Функции, utility types, enums

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Typed API Client

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Типизация функций в TypeScript охватывает параметры, возвращаемое значение и перегрузки. Optional параметры (name?: string), значения по умолчанию (size = 'md') и rest (...args: number[]) типизируются явно. Return type можно вывести (inference), но явный return полезен для публичного API — компилятор проверит, что все ветки возвращают заявленный тип.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Utility types трансформируют существующие типы: Partial<T> делает все поля опциональными (удобно для update DTO), Pick<T, 'title' | 'done'> выбирает подмножество полей, Omit<T, 'id'> исключает поля, Record<Keys, Type> строит объект с заданными ключами. Пример: type UpdateTodo = Partial<Pick<Todo, 'title' | 'done'>> — обновление только разрешённых полей.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        enum в modern TypeScript уступает union of literals: const STATUS = { LOADING: 'loading', SUCCESS: 'success' } as const; type Status = typeof STATUS[keyof typeof STATUS]. Такой подход лучше tree-shaking и не генерирует лишний JS. Function overloads задают несколько сигнатур для одной реализации. Parameters<T> и ReturnType<T> извлекают типы из существующих функций. Оператор satisfies (TS 4.9+) проверяет тип, сохраняя literal inference.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Handbook: Utility Types\n- Handbook: More on Functions\n- TypeScript 4.9: satisfies

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: utility types — конструктор из существующих типов; Partial/Pick/Omit заменяют ручное дублирование DTO.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. UpdateTodo = Partial<Pick<Todo, 'title' | 'done'>>
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Record<Theme, string> для CSS-переменных по темам
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Замени enum статусов на as const объект + union type
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Overload: createElement(tag: 'div'): HTMLDivElement (упрощённо)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Типизируй EventEmitter из недели 9 generics <T>
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Required<Pick<Todo, 'title'>> для create DTO
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Используй ReturnType<typeof fetchJson> в обёртке
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Partial/Pick/Omit в рефакторинге

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] const assertion вместо enum

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] EventEmitter типизирован

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. UpdateTodo = Partial<Pick<Todo, 'title' | 'done'>>
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Record<Theme, string> для CSS-переменных по темам
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Замени enum статусов на as const объект + union type
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Overload: createElement(tag: 'div'): HTMLDivElement (упрощённо)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-10\n\ngit add src/lib/event-emitter.ts\n\ngit commit -m "week-10 day-05: utility types и типизированный EventEmitter"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): TS + React setup

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Typed API Client

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Vite — современный инструмент сборки для фронтенда с мгновенным dev-сервером и HMR (Hot Module Replacement). Создание React + TypeScript проекта: npm create vite@latest my-app -- --template react-ts. Структура: src/main.tsx — точка входа, App.tsx — корневой компонент, vite-env.d.ts — типы Vite. TypeScript настроен из коробки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Props React-компонента типизируются через interface: interface ButtonProps { label: string; onClick: () => void; variant?: 'primary' | 'secondary'; disabled?: boolean }. Современная рекомендация — обычная функция function Button({ label, onClick }: ButtonProps), а не React.FC (устаревший паттерн с неявным children). React.ReactNode описывает всё, что можно отрендерить (строки, числа, элементы, массивы, null). React.ReactElement — конкретно JSX-элемент.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Vite конфигурируется в vite.config.ts; path aliases настраиваются и в tsconfig, и в vite. React Strict Mode в dev намеренно вызывает двойной render компонентов, чтобы выявить побочные эффекты — это нормально и не баг. Команды: npm run dev (разработка), npm run build (production-сборка с проверкой типов).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- React TypeScript Cheatsheet: Setup\n- Vite Guide\n- react.dev: Quick Start

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: Vite + react-ts даёт типизированный старт за минуту; props типизируй через interface, не через React.FC.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай проект Vite + React + TypeScript в week-10/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перенеси типы Todo в src/types/todo.ts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Компонент Button с props: label, onClick, variant?, disabled?
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Компонент Card с children: React.ReactNode
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Запусти npm run dev, убедись что HMR работает
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Компонент TodoItem с типизированными props из types/todo.ts
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь npm run build — production без ошибок TS
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Vite проект запускается

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Минимум 2 типизированных компонента

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Типы вынесены в отдельные файлы

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай проект Vite + React + TypeScript в week-10/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перенеси типы Todo в src/types/todo.ts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Компонент Button с props: label, onClick, variant?, disabled?
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Компонент Card с children: React.ReactNode
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-10\n\ngit add src/components/\n\ngit commit -m "week-10 day-06: Vite react-ts, Button и Card"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Миграция и strict mode

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Typed API Client

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Миграция существующего JS-проекта на TypeScript может быть постепенной. В tsconfig.json включи allowJs: true — компилятор будет проверять .js файлы рядом с .ts. checkJs: true добавляет проверку типов в JS через JSDoc-аннотации. Переименовывай файлы по одному: api.jsapi.ts, исправляй ошибки, коммить.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Типы для npm-пакетов без встроенной типизации лежат в DefinitelyTyped: @types/react, @types/node. Declaration files (.d.ts) описывают форму JS-модуля без реализации — нужны для legacy-библиотек. Path aliases в tsconfig (\"@/*\": [\"src/*\"]) и в vite.config.ts сокращают импорты: import { Button } from '@/components/Button'.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Строгие опции поверх strict: noUncheckedIndexedAccess добавляет | undefined к arr[i] и obj[key] — заставляет проверять границы. exactOptionalPropertyTypes различает «поле отсутствует» и «поле равно undefined». Документируй решения tsconfig в docs/typescript.md — будущий ты (и команда) скажут спасибо.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Handbook: Migrating from JavaScript\n- DefinitelyTyped\n- TSConfig: noUncheckedIndexedAccess

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: миграция на TS — итеративный процесс; strict-опции и path aliases делают кодовую базу надёжнее с каждым коммитом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Настрой alias @/ в tsconfig и vite.config
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Мигрируй api-модуль в TS с полной типизацией
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Включи noUncheckedIndexedAccess — исправь новые ошибки
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Напиши .d.ts для маленькой JS-библиотеки без типов (mock)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Документируй tsconfig решения в docs/typescript.md
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Собери Typed API Client — финальная структура пакета
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-10-done после проверки strict mode
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Path aliases работают

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] api модуль полностью типизирован

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] noUncheckedIndexedAccess не ломает сборку

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Настрой alias @/ в tsconfig и vite.config
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Мигрируй api-модуль в TS с полной типизацией
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Включи noUncheckedIndexedAccess — исправь новые ошибки
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Напиши .d.ts для маленькой JS-библиотеки без типов (mock)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-10\n\ngit add .\n\ngit commit -m "week-10 day-07: strict tsconfig и Typed API Client"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Typed API Client — TS-библиотека + Vite React shell. Подробное ТЗ: docs/projects.md — Неделя 10.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пакет: типы, generic fetchJson<T>, localStorage repo, unit-типы для всех функций. React: заглушка App с Button и Card.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Generic HTTP-клиент с Result<T> pattern и обработкой ошибок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Типизированный репозиторий Todo в localStorage

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          DTO для create/update через Partial/Pick

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          React shell: демо-компоненты, подключение типов из библиотеки

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] strict TypeScript, zero any в src/

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Generics в fetch и storage

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Utility types для update DTOs

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Vite react-ts scaffold с 2+ компонентами

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] docs/typescript.md с объяснением tsconfig

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] README с npm run build и npm run dev

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тег week-10-done

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Зачем TypeScript если есть JS?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Разница interface и type?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Когда unknown лучше any?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Что делает Partial<T> и Pick<T, K>?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Как типизировать props React-компонента?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Typed API Client** в `learning-log/week-10/`, осмысленная Git-история, тег `week-10-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nTypeScript strict: типы без any\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-10-day-1", "label": "День 1 (Mon): Введение в TypeScript"}, {"id": "week-10-day-2", "label": "День 2 (Tue): Типы, union, literal, any"}, {"id": "week-10-day-3", "label": "День 3 (Wed): Interfaces и type aliases"}, {"id": "week-10-day-4", "label": "День 4 (Thu): Generics — основы"}, {"id": "week-10-day-5", "label": "День 5 (Fri): Функции, utility types, enums"}, {"id": "week-10-day-6", "label": "День 6 (Sat): TS + React setup"}, {"id": "week-10-day-7", "label": "День 7 (Sun): Миграция и strict mode"}, {"id": "week-10-project", "label": "Проект недели"}, {"id": "week-10-review", "label": "Ревью-чеклист"}], "text": "Неделя 10: TypeScript — типы, interfaces, generics basics, TS+React setup Цель недели: освоить основы TypeScript и подготовить проект к React с типизированной кодовой базой. Литература: TypeScript Handbook , learn.javascript.ru: Типы , React TypeScript Cheatsheet , Total TypeScript — Beginners , TSConfig Reference Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-10/ День 1 (Mon): Введение в TypeScript Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Typed API Client Теория TypeScript — это надмножество JavaScript со статической системой типов. Код пишется в .ts (или .tsx для JSX), компилируется компилятором tsc в обычный JavaScript, котор…"} \ No newline at end of file +{"id": "week-10", "title": "TypeScript", "fullTitle": "Неделя 10: TypeScript — типы, interfaces, generics basics, TS+React setup", "html": "

                                                                                                                                                                                                                        Неделя 10: TypeScript — типы, interfaces, generics basics, TS+React setup

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: освоить основы TypeScript и подготовить проект к React с типизированной кодовой базой.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература: TypeScript Handbook, learn.javascript.ru: Типы, React TypeScript Cheatsheet, Total TypeScript — Beginners, TSConfig Reference

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git: минимум 1 осмысленный коммит каждый день в learning-log/week-10/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Введение в TypeScript

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Typed API Client

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        TypeScript — это надмножество JavaScript со статической системой типов. Код пишется в .ts (или .tsx для JSX), компилируется компилятором tsc в обычный JavaScript, который выполняется в браузере или Node.js. Типы существуют только на этапе разработки и стираются при компиляции — в runtime никакой проверки типов нет. Зато IDE и компилятор ловят ошибки до запуска: опечатки в свойствах, неверные аргументы, забытые null.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Установка: npm init -y, npm i -D typescript, npx tsc --init создаёт tsconfig.json. Ключевые опции: strict: true (включает все строгие проверки), target (версия JS на выходе), module (система модулей), outDir и rootDir. Базовые типы: string, number, boolean, null, undefined, bigint, symbol. Аннотация явная: let name: string = 'Anna', но чаще полагайся на вывод типов (inference): const count = 0 → TypeScript сам определит number.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Команда npx tsc --noEmit проверяет типы без генерации файлов — удобно в CI. Разница .ts и .tsx: JSX-синтаксис допустим только в .tsx. Скрипт \"build\": \"tsc\" в package.json автоматизирует компиляцию, \"dev\": \"tsc --watch\" пересобирает при каждом сохранении.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Хорошая мысленная модель TypeScript — строительные леса вокруг здания: леса (типы) помогают безопасно и быстро строить, показывают, где не хватает опоры, но к моменту сдачи объекта (компиляции в JS) их полностью убирают — в готовом здании (браузере) лесов уже нет, только сам дом. Именно поэтому в runtime нет проверки типов: interface User не существует после компиляции, это чисто инструмент разработки, а не часть исполняемой программы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эта неделя — фундамент для всего оставшегося курса: React-компоненты, их props, состояние и API-слои в дальнейшем описываются практически исключительно на TypeScript, и большинство современных вакансий junior-frontend разработчика требуют именно TS, а не чистый JS. Инвестиция в понимание типов сейчас окупится кратно уже на неделе 11.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что TypeScript «медленнее» JavaScript в исполнении: это неверно, поскольку типы стираются до запуска, и скомпилированный .js-файл работает ровно с той же скоростью, что и написанный вручную JS. Единственная «цена» TypeScript — время компиляции (tsc) перед запуском, а не runtime-производительность. Конкретный пример пользы: function add(a: number, b: number) { return a + b }, вызванная как add('2', '3'), немедленно подсветится редактором как ошибка ещё до сохранения файла — в чистом JS та же ошибка обнаружилась бы только в runtime как склейка строк '23' вместо ожидаемого 5, и такую опечатку легко пропустить в задании 4 практики («исправь все ошибки компиляции»).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- TypeScript: Getting Started\n- learn.javascript.ru: Типы\n- TSConfig Reference

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: TypeScript ловит целый класс ошибок на этапе компиляции — типы это документация, которую нельзя проигнорировать.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай проект learning-log/week-10, инициализируй TypeScript
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перепиши utils.js из прошлых недель в utils.ts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Включи strict: true в tsconfig.json
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Исправь все ошибки компиляции
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Настрой скрипт \"build\": \"tsc\" в package.json
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь \"dev\": \"tsc --watch\" для автопересборки
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Создай src/index.ts — точка входа, импорт utils
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] tsc компилирует без ошибок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] strict: true включён

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Понимаю разницу .ts и .js на выходе

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай проект learning-log/week-10, инициализируй TypeScript
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перепиши utils.js из прошлых недель в utils.ts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Включи strict: true в tsconfig.json
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Исправь все ошибки компиляции
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-10\n\ngit add package.json tsconfig.json src/\n\ngit commit -m "week-10 day-01: инициализация TS-проекта и utils.ts"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Типы, union, literal, any

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Typed API Client

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Union types объединяют несколько типов: string | number означает «или строка, или число». Literal types сужают множество до конкретных значений: type Theme = 'light' | 'dark' — не любая строка, а ровно два варианта. TypeScript не даст присвоить 'blue', если тип допускает только 'light' | 'dark'. Это основа для моделирования состояний и флагов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        any отключает проверку типов — «дыра» в системе, через которую ошибки просачиваются обратно в runtime. Избегай any; вместо него используй unknown — тип «что-то есть, но мы не знаем что». С unknown нельзя ничего делать, пока не сузишь тип через typeof, in или type guard. Discriminated union добавляет общее поле-дискриминатор: { ok: true, data: T } | { ok: false, error: string } — switch по ok сужает тип в каждой ветке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        as const делает объект readonly с literal-типами: const STATUS = { LOADING: 'loading' } as const. Тип never означает «недостижимо» — полезен в exhaustive switch: если добавишь новый вариант union, компилятор укажет на непокрытую ветку. Пользовательские type guards: function isUser(x: unknown): x is User — явный контракт сужения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель union type — меню с ограниченным выбором, а не открытый вопрос «что хочешь съесть»: type Theme = 'light' | 'dark' — это меню из двух блюд, и компилятор физически не позволит «заказать» 'blue', потому что такого пункта нет. Это резко отличается от обычного string, который допускает любую строку — как меню без ограничений, где легко случайно заказать несуществующее блюдо и получить ошибку уже на кухне (в runtime).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Discriminated union и exhaustive switch — техника, которая будет использоваться постоянно при моделировании ответов API (успех/ошибка) и состояний UI (loading/success/error/empty, как в неделе 8) — только теперь эти состояния описываются типом, а не просто строкой, и компилятор гарантирует, что ни одна ветка не забыта. Это прямая подготовка к React, где состояния компонентов часто моделируются именно так.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать any и unknown взаимозаменяемыми, потому что оба «принимают что угодно». Разница принципиальна: any отключает все проверки для значения и всего, что из него получено (заражает код), а unknown требует явно сузить тип перед использованием — const x: unknown = data; x.toUpperCase() не скомпилируется, пока не добавишь if (typeof x === 'string'). Конкретный пример из практики: функция formatId(id: string | number), где внутри нужно явно проверить typeof id === 'string', прежде чем вызвать .toUpperCase() — иначе компилятор справедливо укажет, что у number такого метода нет.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Handbook: Everyday Types\n- Handbook: Narrowing\n- Total TypeScript: Beginners

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: union + narrowing превращают TypeScript в инструмент моделирования состояний; unknown безопаснее any.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Тип Theme = 'light' | 'dark' для переключателя темы
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Функция formatId(id: string | number): string с narrowing
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Замени any на unknown + проверку перед использованием
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Discriminated union Result = { ok: true, data: T } | { ok: false, error: string }
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Используй as const для объекта констант STATUS
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Напиши type guard isApiError(err): err is ApiError
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Exhaustive switch по union — default: const _exhaustive: never = value
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет any в новом коде

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Union types с корректным narrowing

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Result pattern для ошибок API

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Тип Theme = 'light' | 'dark' для переключателя темы
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Функция formatId(id: string | number): string с narrowing
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Замени any на unknown + проверку перед использованием
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Discriminated union Result = { ok: true, data: T } | { ok: false, error: string }
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-10\n\ngit add src/types/\n\ngit commit -m "week-10 day-02: union, Result pattern и type guards"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          any распространяется как зараза — теряется смысл TS

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Утверждение as Type без проверки — ложная безопасность

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Забытый strictNullChecks — null не ловится

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): Interfaces и type aliases

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Typed API Client

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Объекты в TypeScript описываются через interface или type. interface User { id: number; name: string; email?: string }email? опционален, его может не быть. readonly id: number запрещает переприсвоение после создания. Оба способа описывают форму объекта; различия тонкие: interface можно расширять (extends) и объединять (declaration merging), type гибче для union и mapped types.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Расширение: interface Admin extends User { role: string } добавляет поля. Альтернатива — intersection: type Admin = User & { role: string }. Index signature [key: string]: string описывает объекты с динамическими ключами (словари, кэши). Для объектов предпочитай interface, для union и вычисляемых типов — type.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Utility types из коробки: Readonly<T> делает все поля readonly, ReadonlyArray<T> — неизменяемый массив. В проекте заведи папку types/ с DTO (Data Transfer Objects): Todo, ApiResponse<T>, PaginationMeta. Типизированный api-модуль возвращает Promise<ApiResponse<Todo[]>> вместо «что-то пришло с сервера». Это контракт между слоями, который компилятор проверяет.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель interface/type — бланк договора между частями программы: до того как API-функция вернёт данные, интерфейс уже фиксирует, какие поля там будут и какого они типа — это контракт, который компилятор проверяет на каждом использовании, а не просто комментарий-пожелание. Если сервер изменит форму ответа, а DTO забудут обновить, TypeScript не поймает несоответствие с реальным JSON (он не знает про сеть), но зато любой код внутри приложения, который ожидает поля по старому контракту, останется согласованным и предсказуемым.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Явные DTO в отдельной папке types/ становятся особенно ценными на неделе 11: типы Todo, ApiResponse<T> из этой недели практически без изменений переедут в React-компоненты как типы props, избавляя от необходимости придумывать их заново. Хорошо спроектированные интерфейсы на этой неделе — это меньше работы на следующей.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — воспринимать interface и type как взаимоисключающий выбор «правильного» и «неправильного» инструмента: в большинстве junior-задач разница не критична, и команды чаще выбирают один стиль как конвенцию проекта, а не по глубоким техническим причинам. Единственный практический критерий, который стоит запомнить: если нужен union ('a' | 'b') или вычисляемый тип — это всегда type, поскольку interface такого не умеет; если нужно расширяемое описание формы объекта с возможностью declaration merging — чуть удобнее interface. Задание 4 практики («расширь User → Admin») — хороший повод попробовать оба варианта (extends и &) и увидеть, что результат идентичен.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Handbook: Objects\n- Handbook: Utility Types\n- React TypeScript Cheatsheet

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: interface/type — это контракт формы данных; DTO в отдельных файлах делают API и доменную модель явными.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Интерфейсы Todo, TodoFilter, TodoState для Todo App
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. interface ApiResponse<T> { data: T; meta: PaginationMeta }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Type alias для функции: type EventHandler = (e: Event) => void
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Расширь UserAdmin с полем permissions: string[]
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Рефакторинг api-модуля с типизированными ответами
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай types/api.ts — все DTO в одном месте
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь readonly к id в Todo — попробуй изменить и поймай ошибку TS
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Все доменные сущности типизированы

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] interface vs type — осознанный выбор

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Опциональные и readonly поля использованы

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Интерфейсы Todo, TodoFilter, TodoState для Todo App
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. interface ApiResponse<T> { data: T; meta: PaginationMeta }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Type alias для функции: type EventHandler = (e: Event) => void
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Расширь UserAdmin с полем permissions: string[]
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-10\n\ngit add src/types/ src/api/\n\ngit commit -m "week-10 day-03: интерфейсы Todo и ApiResponse"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): Generics — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Typed API Client

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Generics (обобщения) позволяют писать функции и типы, работающие с разными типами, сохраняя связь между входом и выходом. function identity<T>(arg: T): T — тип возвращаемого значения совпадает с типом аргумента. Без generics пришлось бы писать отдельные функции для string, number, User или откатываться к any.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Constraints ограничивают generic сверху: <T extends { id: number }> гарантирует, что у T есть поле id. keyof T даёт union всех ключей объекта, а indexed access T[K] — тип значения по ключу. Это основа для pluck(obj, 'name') с правильным return type. Generic defaults <T = string> задают тип по умолчанию, если параметр не указан.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практические применения: async function fetchJson<T>(url: string): Promise<T> типизирует ответ API; getItem<T>(key: string): T | null типизирует localStorage wrapper; groupBy<T, K extends string>(items, keyFn) группирует массив любых объектов. IDE будет подсказывать поля на результате fetchJson<User[]>(url) без ручных кастов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель generic — форма для отливки, которая подходит под любой материал, но сохраняет форму: function identity<T>(arg: T): T — это форма, куда можно залить строку, число или объект, и на выходе гарантированно получить то же самое, что залили, а не что-то другое. Без generics пришлось бы либо копировать функцию под каждый тип материала, либо использовать any — и тогда форма перестаёт что-либо гарантировать, превращаясь в дырявое ведро.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Generics — пожалуй, самая мощная идея TypeScript для junior-разработчика, потому что она напрямую используется в React: useState<Todo[]>([]), useRef<HTMLInputElement>(null), useContext<AuthContextType> — все эти хуки на неделе 11 и позже являются generic-функциями. Тот, кто разобрался с fetchJson<T> сегодня, не удивится синтаксису useState<T> через несколько недель.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — путать generic-параметр <T> с типом any, считая, что раз буква T может быть «чем угодно», значит проверки нет вообще. На самом деле после того, как T определён при вызове (fetchJson<User>(url)), TypeScript отслеживает его строго во всей функции. Конкретный пример пользы: const user = await fetchJson<User>('/api/user') даёт автодополнение по полям user.name, user.email прямо в IDE — тогда как fetchJson('/api/user') без указания типа вернёт unknown, и обратиться к .name без явной проверки не получится, что стоит заметить в задании 7 практики («проверь inference в IDE»).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ещё один полезный приём — generic по умолчанию: class ApiClient<T = unknown> позволяет использовать new ApiClient() без явного указания типа, если он не критичен в конкретном месте, но при необходимости уточнить его как new ApiClient<User>(). Это балансирует гибкость и строгость, не заставляя писать <T> там, где тип и так очевиден из контекста.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Handbook: Generics\n- Handbook: Keyof Types\n- Total TypeScript: Beginners

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: generics связывают типы входа и выхода — fetchJson<User> безопаснее fetchJson<any>.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. function first<T>(arr: T[]): T | undefined
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. async function fetchJson<T>(url: string): Promise<T> — типизированный fetch
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. function groupBy<T, K extends string>(items: T[], key: (item: T) => K)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Типизируй localStorage wrapper: getItem<T>(key): T | null
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Примени generics в api-клиенте каталога фильмов
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. function pluck<T, K extends keyof T>(obj: T, key: K): T[K]
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Напиши тестовые вызовы с разными T — проверь inference в IDE
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] fetchJson типизирует ответ API

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] groupBy работает с разными типами

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Constraints использован хотя бы раз

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. function first<T>(arr: T[]): T | undefined
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. async function fetchJson<T>(url: string): Promise<T> — типизированный fetch
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. function groupBy<T, K extends string>(items: T[], key: (item: T) => K)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Типизируй localStorage wrapper: getItem<T>(key): T | null
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-10\n\ngit add src/lib/fetch.ts src/lib/storage.ts\n\ngit commit -m "week-10 day-04: generic fetchJson и localStorage wrapper"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Функции, utility types, enums

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Typed API Client

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Типизация функций в TypeScript охватывает параметры, возвращаемое значение и перегрузки. Optional параметры (name?: string), значения по умолчанию (size = 'md') и rest (...args: number[]) типизируются явно. Return type можно вывести (inference), но явный return полезен для публичного API — компилятор проверит, что все ветки возвращают заявленный тип.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Utility types трансформируют существующие типы: Partial<T> делает все поля опциональными (удобно для update DTO), Pick<T, 'title' | 'done'> выбирает подмножество полей, Omit<T, 'id'> исключает поля, Record<Keys, Type> строит объект с заданными ключами. Пример: type UpdateTodo = Partial<Pick<Todo, 'title' | 'done'>> — обновление только разрешённых полей.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        enum в modern TypeScript уступает union of literals: const STATUS = { LOADING: 'loading', SUCCESS: 'success' } as const; type Status = typeof STATUS[keyof typeof STATUS]. Такой подход лучше tree-shaking и не генерирует лишний JS. Function overloads задают несколько сигнатур для одной реализации. Parameters<T> и ReturnType<T> извлекают типы из существующих функций. Оператор satisfies (TS 4.9+) проверяет тип, сохраняя literal inference.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель utility types — конструктор Lego, где из готовых кубиков (существующих типов) собираются новые формы без ручной лепки с нуля: Partial<Todo> берёт тип Todo и говорит «все поля теперь опциональны», Pick<Todo, 'title'> — «оставь только эту деталь», Omit<Todo, 'id'> — «убери эту деталь, остальное оставь». Это избавляет от ручного дублирования почти идентичных интерфейсов для create/update/read версий одной и той же сущности.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эти приёмы напрямую переносятся в API-слои React-приложений: типичный паттерн type CreateTodoDto = Omit<Todo, 'id' | 'createdAt'> (сервер сам генерирует id и дату) встречается в подавляющем большинстве реальных проектов, и понимание его сегодня избавит от копипасты интерфейсов позже. Замена enum на as const объект — тоже не просто вкусовщина: enum исторически генерирует дополнительный JS-код при компиляции, тогда как as const полностью стирается, что мельче бандл и лучше tree-shaking для production-сборки на Vite (день 6 этой недели).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что Partial<T> делает объект необязательным целиком, а не каждое поле по отдельности: Partial<Todo> всё ещё требует объект (не undefined), просто каждое его свойство (title, done) можно опустить. Конкретный пример из практики: type UpdateTodo = Partial<Pick<Todo, 'title' | 'done'>> описывает ровно то, что можно менять при PATCH-запросе — не весь Todo целиком и не произвольные поля, а только title и done, оба опционально.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Handbook: Utility Types\n- Handbook: More on Functions\n- TypeScript 4.9: satisfies

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: utility types — конструктор из существующих типов; Partial/Pick/Omit заменяют ручное дублирование DTO.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. UpdateTodo = Partial<Pick<Todo, 'title' | 'done'>>
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Record<Theme, string> для CSS-переменных по темам
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Замени enum статусов на as const объект + union type
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Overload: createElement(tag: 'div'): HTMLDivElement (упрощённо)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Типизируй EventEmitter из недели 9 generics <T>
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Required<Pick<Todo, 'title'>> для create DTO
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Используй ReturnType<typeof fetchJson> в обёртке
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Partial/Pick/Omit в рефакторинге

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] const assertion вместо enum

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] EventEmitter типизирован

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. UpdateTodo = Partial<Pick<Todo, 'title' | 'done'>>
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Record<Theme, string> для CSS-переменных по темам
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Замени enum статусов на as const объект + union type
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Overload: createElement(tag: 'div'): HTMLDivElement (упрощённо)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-10\n\ngit add src/lib/event-emitter.ts\n\ngit commit -m "week-10 day-05: utility types и типизированный EventEmitter"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): TS + React setup

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Typed API Client

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Vite — современный инструмент сборки для фронтенда с мгновенным dev-сервером и HMR (Hot Module Replacement). Создание React + TypeScript проекта: npm create vite@latest my-app -- --template react-ts. Структура: src/main.tsx — точка входа, App.tsx — корневой компонент, vite-env.d.ts — типы Vite. TypeScript настроен из коробки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Props React-компонента типизируются через interface: interface ButtonProps { label: string; onClick: () => void; variant?: 'primary' | 'secondary'; disabled?: boolean }. Современная рекомендация — обычная функция function Button({ label, onClick }: ButtonProps), а не React.FC (устаревший паттерн с неявным children). React.ReactNode описывает всё, что можно отрендерить (строки, числа, элементы, массивы, null). React.ReactElement — конкретно JSX-элемент.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Vite конфигурируется в vite.config.ts; path aliases настраиваются и в tsconfig, и в vite. React Strict Mode в dev намеренно вызывает двойной render компонентов, чтобы выявить побочные эффекты — это нормально и не баг. Команды: npm run dev (разработка), npm run build (production-сборка с проверкой типов).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель Vite — конвейер быстрой сборки с горячей заменой деталей на ходу: вместо того чтобы каждый раз пересобирать весь автомобиль (bundle) с нуля при малейшей правке, HMR подменяет только изменённую деталь (модуль) прямо во время движения, не перезагружая всю страницу и сохраняя текущее состояние компонентов (например, введённый в форму текст).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Всё, что изучалось эту неделю — интерфейсы, generics, utility types — сходится именно здесь: типизация props компонента — первое место, где TypeScript встречается с React напрямую, и качество этого стыка определяет, насколько безопасно можно будет рефакторить компоненты в дальнейшем на неделе 11. Хорошо типизированный ButtonProps — это защита от передачи onClick={someString} по ошибке, которую поймает компилятор, а не пользователь в браузере.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — использовать React.FC<Props> для типизации компонентов по старой памяти из туториалов пятилетней давности: современное сообщество React рекомендует обычную функцию с типизированными параметрами (function Button(props: ButtonProps)), поскольку React.FC неявно добавляет children всем компонентам (даже тем, где children не предполагается) и хуже работает с generic-компонентами. Конкретный пример из задания 4 практики — Card с children: React.ReactNode: ReactNode покрывает всё, что React способен отрендерить (строка, число, JSX, массив, null), тогда как ReactElement — только конкретный JSX-элемент.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ещё одна деталь, которая экономит время: файлы Vite с JSX обязаны иметь расширение .tsx, а не .ts — компилятор попросту не поймёт синтаксис <div> внутри .ts-файла и попытается интерпретировать угловые скобки как generic-приведение типов, выдав криптичную ошибку. Эта путаница — частая причина первых «непонятных» ошибок при переносе логики из .ts в компонент.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- React TypeScript Cheatsheet: Setup\n- Vite Guide\n- react.dev: Quick Start

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: Vite + react-ts даёт типизированный старт за минуту; props типизируй через interface, не через React.FC.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай проект Vite + React + TypeScript в week-10/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перенеси типы Todo в src/types/todo.ts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Компонент Button с props: label, onClick, variant?, disabled?
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Компонент Card с children: React.ReactNode
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Запусти npm run dev, убедись что HMR работает
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Компонент TodoItem с типизированными props из types/todo.ts
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь npm run build — production без ошибок TS
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Vite проект запускается

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Минимум 2 типизированных компонента

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Типы вынесены в отдельные файлы

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай проект Vite + React + TypeScript в week-10/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перенеси типы Todo в src/types/todo.ts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Компонент Button с props: label, onClick, variant?, disabled?
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Компонент Card с children: React.ReactNode
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-10\n\ngit add src/components/\n\ngit commit -m "week-10 day-06: Vite react-ts, Button и Card"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Миграция и strict mode

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Typed API Client

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Миграция существующего JS-проекта на TypeScript может быть постепенной. В tsconfig.json включи allowJs: true — компилятор будет проверять .js файлы рядом с .ts. checkJs: true добавляет проверку типов в JS через JSDoc-аннотации. Переименовывай файлы по одному: api.jsapi.ts, исправляй ошибки, коммить.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Типы для npm-пакетов без встроенной типизации лежат в DefinitelyTyped: @types/react, @types/node. Declaration files (.d.ts) описывают форму JS-модуля без реализации — нужны для legacy-библиотек. Path aliases в tsconfig (\"@/*\": [\"src/*\"]) и в vite.config.ts сокращают импорты: import { Button } from '@/components/Button'.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Строгие опции поверх strict: noUncheckedIndexedAccess добавляет | undefined к arr[i] и obj[key] — заставляет проверять границы. exactOptionalPropertyTypes различает «поле отсутствует» и «поле равно undefined». Документируй решения tsconfig в docs/typescript.md — будущий ты (и команда) скажут спасибо.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель постепенной миграции — замена деталей в работающем автомобиле на ходу, а не разбор его на запчасти в гараже на неделю: allowJs: true позволяет .ts и .js файлам существовать бок о бок и импортировать друг друга, пока файлы переименовываются по одному (api.jsapi.ts), а не одним гигантским коммитом, который рискует сломать всё сразу и который невозможно нормально код-ревьюить.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Этот навык напрямую пригодится в реальной работе: подавляющее большинство существующих production-кодовых баз в индустрии — это не написанный с нуля на строгом TypeScript проект, а именно постепенно мигрирующий JS-код, и умение делать это безопасно, файл за файлом, ценится не меньше умения писать типы с нуля. noUncheckedIndexedAccess — одна из самых важных строгих опций, о которой часто не знают даже после нескольких месяцев с TypeScript.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать, что strict: true уже покрывает все возможные проверки безопасности типов: на самом деле noUncheckedIndexedAccess не входит в strict по историческим причинам обратной совместимости, и без неё const item = arr[999] в массиве из трёх элементов будет типизирован как обычный элемент, а не T | undefined, хотя в runtime там окажется undefined — источник классических «Cannot read property of undefined» уже после успешной компиляции. Задание 3 практики («включи noUncheckedIndexedAccess — исправь новые ошибки») специально показывает, сколько скрытых мест в коде полагались на удачу при обращении по индексу.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не стоит включать все строгие опции разом «для галочки»: каждая новая опция может вскрыть десятки мест в существующем коде, требующих исправления, и разумнее включать их по одной, коммитить исправления отдельно и двигаться к максимальной строгости постепенно — это тот же принцип итеративной миграции, что и с самим переходом с JS на TS.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Handbook: Migrating from JavaScript\n- DefinitelyTyped\n- TSConfig: noUncheckedIndexedAccess

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: миграция на TS — итеративный процесс; strict-опции и path aliases делают кодовую базу надёжнее с каждым коммитом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Настрой alias @/ в tsconfig и vite.config
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Мигрируй api-модуль в TS с полной типизацией
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Включи noUncheckedIndexedAccess — исправь новые ошибки
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Напиши .d.ts для маленькой JS-библиотеки без типов (mock)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Документируй tsconfig решения в docs/typescript.md
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Собери Typed API Client — финальная структура пакета
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-10-done после проверки strict mode
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Path aliases работают

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] api модуль полностью типизирован

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] noUncheckedIndexedAccess не ломает сборку

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Настрой alias @/ в tsconfig и vite.config
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Мигрируй api-модуль в TS с полной типизацией
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Включи noUncheckedIndexedAccess — исправь новые ошибки
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Напиши .d.ts для маленькой JS-библиотеки без типов (mock)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-10\n\ngit add .\n\ngit commit -m "week-10 day-07: strict tsconfig и Typed API Client"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Typed API Client — TS-библиотека + Vite React shell. Подробное ТЗ: docs/projects.md — Неделя 10.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Пакет: типы, generic fetchJson<T>, localStorage repo, unit-типы для всех функций. React: заглушка App с Button и Card.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Generic HTTP-клиент с Result<T> pattern и обработкой ошибок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Типизированный репозиторий Todo в localStorage

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          DTO для create/update через Partial/Pick

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          React shell: демо-компоненты, подключение типов из библиотеки

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] strict TypeScript, zero any в src/

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Generics в fetch и storage

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Utility types для update DTOs

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Vite react-ts scaffold с 2+ компонентами

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] docs/typescript.md с объяснением tsconfig

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] README с npm run build и npm run dev

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тег week-10-done

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Зачем TypeScript если есть JS?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Разница interface и type?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Когда unknown лучше any?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Что делает Partial<T> и Pick<T, K>?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Как типизировать props React-компонента?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Typed API Client** в `learning-log/week-10/`, осмысленная Git-история, тег `week-10-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nTypeScript strict: типы без any\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-10-day-1", "label": "День 1 (Mon): Введение в TypeScript"}, {"id": "week-10-day-2", "label": "День 2 (Tue): Типы, union, literal, any"}, {"id": "week-10-day-3", "label": "День 3 (Wed): Interfaces и type aliases"}, {"id": "week-10-day-4", "label": "День 4 (Thu): Generics — основы"}, {"id": "week-10-day-5", "label": "День 5 (Fri): Функции, utility types, enums"}, {"id": "week-10-day-6", "label": "День 6 (Sat): TS + React setup"}, {"id": "week-10-day-7", "label": "День 7 (Sun): Миграция и strict mode"}, {"id": "week-10-project", "label": "Проект недели"}, {"id": "week-10-review", "label": "Ревью-чеклист"}], "text": "Неделя 10: TypeScript — типы, interfaces, generics basics, TS+React setup Цель недели: освоить основы TypeScript и подготовить проект к React с типизированной кодовой базой. Литература: TypeScript Handbook , learn.javascript.ru: Типы , React TypeScript Cheatsheet , Total TypeScript — Beginners , TSConfig Reference Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-10/ День 1 (Mon): Введение в TypeScript Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Typed API Client Теория TypeScript — это надмножество JavaScript со статической системой типов. Код пишется в .ts (или .tsx для JSX), компилируется компилятором tsc в обычный JavaScript, котор…"} \ No newline at end of file diff --git a/docs/weeks/11.json b/docs/weeks/11.json index 6cddcfe..d7d13c4 100644 --- a/docs/weeks/11.json +++ b/docs/weeks/11.json @@ -1 +1 @@ -{"id": "week-11", "title": "React basics", "fullTitle": "Неделя 11: React — компоненты, JSX, props, Vite, первые компоненты", "html": "

                                                                                                                                                                                                                        Неделя 11: React — компоненты, JSX, props, Vite, первые компоненты

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: создать первое React-приложение на Vite, освоить компоненты, JSX, props и базовые паттерны.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература: react.dev Learn, React TypeScript Cheatsheet, Vite Guide, Thinking in React, React — Quick Start

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git: минимум 1 осмысленный коммит каждый день в learning-log/week-11/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Введение в React и JSX

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        React — библиотека для построения пользовательских интерфейсов на основе компонентов. Компонент — это JavaScript-функция (или класс), которая принимает props и возвращает описание UI. React берёт это описание и обновляет реальный DOM эффективно через Virtual DOM и reconciliation. Философия React: UI = f(state) — интерфейс является функцией от состояния.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        JSX — синтаксическое расширение, которое выглядит как HTML, но компилируется в вызовы React.createElement. Правила JSX отличаются от HTML: className вместо class, htmlFor вместо for, все теги закрываются (<img />, <br />). В фигурных скобках {expression} встраивается любое JavaScript-выражение: переменные, вызовы функций, тернарные операторы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Компоненты именуются в PascalCase (Header, TodoItem), а props — в camelCase. JSX автоматически экранирует строки — вставка пользовательского текста безопасна от XSS. Компонент должен возвращать один корневой элемент; если нужно несколько соседних без обёрточного <div>, используй Fragment: <>...</>. Не вызывай компоненты как обычные функции Header() — только через JSX <Header />, иначе React не отследит жизненный цикл и hooks.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- react.dev: Describing the UI\n- react.dev: Writing Markup with JSX\n- React — Quick Start

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: компонент — функция от props к UI; JSX — удобный синтаксис описания, а не HTML.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Изучи структуру Vite react-ts проекта из недели 10
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Очисти App.tsx, создай разметку лендинга в JSX
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Вынеси Header, Footer, Hero в отдельные файлы компонентов
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Используй Fragment вместо обёрточного div где возможно
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Подключи CSS-модуль или отдельный App.css
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай learning-log/week-11/ — новый Vite-проект или форк week-10
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь ESLint rules для React (eslint-plugin-react)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Минимум 3 компонента в отдельных файлах

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Корректный JSX без ошибок ESLint

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] className вместо class

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Изучи структуру Vite react-ts проекта из недели 10
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Очисти App.tsx, создай разметку лендинга в JSX
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Вынеси Header, Footer, Hero в отдельные файлы компонентов
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Используй Fragment вместо обёрточного div где возможно
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-11\n\ngit add src/components/\n\ngit commit -m "week-11 day-01: JSX, Header, Footer и Hero"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Props и композиция

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Props (properties) — единственный способ передать данные от родителя к ребёнку в React. Props read-only: дочерний компонент не должен их мутировать. Это основа однонаправленного потока данных (one-way data flow): состояние живёт выше, данные текут вниз через props, события — вверх через callback-функции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Деструктуризация в сигнатуре делает код читаемым: function Button({ label, onClick, variant = 'primary' }) вместо props.label. Значения по умолчанию задавай прямо в деструктуризации. Специальный prop children — содержимое между открывающим и закрывающим тегами: <Card>Это children</Card>. Паттерн slot: Card рендерит children внутри своей разметки, а родитель решает, что туда положить.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Spread props (<Input {...fieldProps} />) передаёт все свойства объекта разом — удобно, но осторожно: лишние props могут попасть на DOM-элемент и вызвать warning. Props drilling на 1–2 уровня — нормальная практика; Context (неделя 13+) понадобится при глубокой вложенности. В TypeScript каждый компонент получает interface XxxProps с явными типами.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- react.dev: Passing Props to a Component\n- react.dev: Thinking in React\n- React TypeScript Cheatsheet: Components

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: props — read-only вход компонента; данные вниз, события вверх через callbacks.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Button с props: variant: 'primary' | 'secondary', size, disabled, onClick
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Card с title, children, опциональным footer
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Avatar с src, alt, size — значения по умолчанию
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Композиция: Card внутри Hero, Button в Card.footer
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Задокументируй props через TypeScript interfaces
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Компонент Icon с name и aria-label для a11y
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Story-подобная страница: все варианты Button на одном экране
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Все props типизированы

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] children используется для композиции

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Default props через деструктуризацию

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Button с props: variant: 'primary' | 'secondary', size, disabled, onClick
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Card с title, children, опциональным footer
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Avatar с src, alt, size — значения по умолчанию
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Композиция: Card внутри Hero, Button в Card.footer
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-11\n\ngit add src/components/ui/\n\ngit commit -m "week-11 day-02: Button, Card, Avatar и композиция"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Мутация props — запрещено

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          key не доступен как prop — отдельный атрибут

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Пропуск alt на img — a11y регрессия

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): Списки, keys и рендеринг

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Списки в React рендерятся через array.map(): каждый элемент массива превращается в JSX. React нужен атрибут key на элементе верхнего уровня в map — уникальный и стабильный идентификатор (обычно item.id). Key помогает reconciliation: React сопоставляет элементы между рендерами и обновляет только изменившиеся, а не пересоздаёт весь список.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Использование индекса массива как key (key={index}) допустимо только для статических списков без reorder/delete. При удалении элемента из середины индексы сдвигаются — React перепутает компоненты, и state (например, фокус input) «переедет» к другому элементу. Всегда предпочитай key={todo.id}.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Условный рендеринг: {isLoggedIn && <Dashboard />} (осторожно — 0 falsy и отрендерится как текст), тернарный {loading ? <Spinner /> : <List />}, early return if (!data) return null. Не вызывай компоненты как функции TodoItem(todo) — только <TodoItem todo={todo} />. Fragment с key нужен при map фрагментов: <Fragment key={id}>...</Fragment>.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- react.dev: Rendering Lists\n- react.dev: Conditional Rendering\n- react.dev: Fragment

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: стабильный key по id — не оптимизация, а корректность при изменении порядка и удалении элементов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Компонент TodoList — рендер массива Todo[]
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. TodoItem с props: todo, onToggle, onDelete
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. keys = todo.id, не индекс массива
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Пустой список: условный рендер «Нет задач»
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Фильтр tabs: all / active / done — условное отображение
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь mock-данные в data/todos.ts — 5+ задач
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь: удаление средней задачи не ломает state остальных
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Стабильные keys на основе id

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Условный рендер для empty state

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] map возвращает JSX, не side effects

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Компонент TodoList — рендер массива Todo[]
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. TodoItem с props: todo, onToggle, onDelete
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. keys = todo.id, не индекс массива
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Пустой список: условный рендер «Нет задач»
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-11\n\ngit add src/components/todo/ src/data/\n\ngit commit -m "week-11 day-03: TodoList, keys и условный рендер"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): События и состояние (useState)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Интерактивность в React начинается с useState — hook, дающий компоненту «память». const [count, setCount] = useState(0) возвращает текущее значение и функцию обновления. Вызов setCount планирует ререндер компонента с новым значением. State — это снимок на момент рендера: если вызвать setCount(count + 1) три раза подряд в одном обработчике, счётчик увеличится на 1, не на 3. Для последовательных обновлений используй функциональную форму: setCount(c => c + 1).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Обновления state должны быть иммутабельными: вместо todos.push(item) пиши setTodos([...todos, item]); вместо todo.done = truesetTodos(todos.map(t => t.id === id ? { ...t, done: true } : t)). React сравнивает ссылки — мутация не вызовет ререндер. Controlled input связывает <input value={text} onChange={e => setText(e.target.value)} /> — React state единственный источник правды для значения поля.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Несколько useState предпочтительнее одного большого объекта state — проще обновлять отдельные поля. Derived values (счётчик активных задач) вычисляй из state при рендере, а не храни в отдельном useState. Batching: React объединяет несколько setState в одном обработчике события в один ререндер.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- react.dev: State: A Component's Memory\n- react.dev: Adding Interactivity\n- react.dev: Queueing a Series of State Updates

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: state обновляй иммутабельно; функциональный апдейт setX(x => ...) даёт актуальное значение при batching.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Счётчик в Hero с useState
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Controlled input: value + onChange для поля новой задачи
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавление задачи в массив через immutable update
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Toggle done: todos.map(t => t.id === id ? {...t, done: !t.done} : t)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Удаление через filter
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Счётчик «активных» задач — derived из state, не отдельный useState
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь createdAt: Date.now() при создании задачи
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Все inputs controlled

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] State обновляется иммутабельно

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет прямой мутации массива todos

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Счётчик в Hero с useState
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Controlled input: value + onChange для поля новой задачи
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавление задачи в массив через immutable update
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Toggle done: todos.map(t => t.id === id ? {...t, done: !t.done} : t)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-11\n\ngit add src/components/todo/\n\ngit commit -m "week-11 day-04: useState, CRUD задач и controlled input"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Формы и подъём состояния

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Формы в React обрабатываются через событие onSubmit на <form> с обязательным e.preventDefault() — иначе браузер перезагрузит страницу. Подъём состояния (lifting state up) — ключевой паттерн: если два компонента (TodoList и FilterTabs) должны разделять данные, state поднимается к их ближайшему общему родителю (TodoApp). Родитель хранит todos и filter, детям передаёт данные и колбэки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Controlled components — стандарт для форм: значение input, textarea, select и checkbox полностью управляется React state. Uncontrolled (через ref) допустим для простых случаев, но controlled даёт полный контроль: валидация, disabled, сброс. Колбэки вниз: onToggle(id), onDelete(id), onFilterChange('active') — дочерний компонент сообщает родителю о действии, не меняя state напрямую.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Валидация на клиенте: проверяй перед submit (пустая задача не добавляется), показывай ошибку рядом с полем. Атрибут name на input важен для autofill и семантики. Disabled кнопка submit при невалидной форме — простая и эффективная UX-защита. Enter в поле ввода сабмитит форму, если input внутри <form>.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- react.dev: Reacting to Input with State\n- react.dev: Sharing State Between Components\n- react.dev: Form

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: общий state — у ближайшего общего родителя; форма controlled, события — через callbacks вверх.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. TodoApp — state todos, filter наверху
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. AddTodoForm — submit добавляет задачу, очищает input
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. FilterTabs — подними filter state, передай setFilter
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. TodoStats — вычисляемые значения из props (active count)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Валидация: пустая задача не добавляется, показ ошибки
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. AddTodoForm — disabled кнопка при пустом поле
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Enter в поле ввода сабмитит форму
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] State в общем родителе TodoApp

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Форма с preventDefault

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Валидация пустого ввода

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. TodoApp — state todos, filter наверху
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. AddTodoForm — submit добавляет задачу, очищает input
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. FilterTabs — подними filter state, передай setFilter
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. TodoStats — вычисляемые значения из props (active count)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-11\n\ngit add src/components/todo/TodoApp.tsx\n\ngit commit -m "week-11 day-05: lifting state, форма и фильтры"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Стилизация и структура проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Стилизация React-приложения начинается с организации, а не с выбора CSS-in-JS библиотеки. CSS Modules изолируют стили: import styles from './Button.module.css' и className={styles.primary} — классы уникальны на уровне файла, нет конфликтов имён. Условные классы удобно собирать через template literal или утилиту cn(...classes), которая фильтрует falsy-значения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура src/ по назначению: components/ui/ — переиспользуемые (Button, Card), components/todo/ — предметные, types/ — TypeScript-интерфейсы, hooks/ — custom hooks (позже), utils/ — чистые функции, data/ — mock-данные. Vite позволяет импортировать изображения как модули: import logo from './logo.svg' — URL подставится автоматически.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тёмная тема через CSS variables: в :root задай --bg: #fff; --text: #111, в .dark переопредели --bg: #111; --text: #fff. Переключение — class на <html> или корневом div, управляемый React state. prefers-color-scheme: dark в media query задаёт системную тему по умолчанию. Mobile-first: базовые стили для узкого экрана, @media (min-width: 768px) для расширения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Vite: Static Assets\n- CSS Modules — spec\n- MDN: CSS custom properties

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: CSS Modules + логичная структура папок + CSS variables для темы — достаточный фундамент без CSS-in-JS.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. CSS Modules для Button, Card, TodoItem
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Утилита cn(...classes) для объединения классов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Реорганизуй src: components/todo/, components/ui/
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Перенеси типы в types/todo.ts, mock data в data/
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Тёмная тема через class на root + CSS variables
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Адаптив: mobile-first для TodoApp (min-width breakpoints)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь контраст текста в обеих темах
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Логичная структура папок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] CSS Modules без глобальных конфликтов

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тема переключается через state + class

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. CSS Modules для Button, Card, TodoItem
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Утилита cn(...classes) для объединения классов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Реорганизуй src: components/todo/, components/ui/
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Перенеси типы в types/todo.ts, mock data в data/
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-11\n\ngit add src/ src/**/*.module.css\n\ngit commit -m "week-11 day-06: CSS Modules, структура и тёмная тема"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Сборка Todo App и деплой

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Завершение Todo App объединяет state, effects и production-сборку. useEffect — hook для синхронизации React state с внешним миром (localStorage, document.title, подписки). Для persist: useEffect(() => { localStorage.setItem('todos', JSON.stringify(todos)) }, [todos]) — сохраняй при каждом изменении. Начальное значение загружай через lazy init: useState(() => JSON.parse(localStorage.getItem('todos') ?? '[]')).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Production-сборка: npm run build создаёт оптимизированный bundle в dist/, npm run preview проверяет его локально. Деплой на GitHub Pages, Netlify или Vercel — статический хостинг для SPA. Для GitHub Pages задай base в vite.config.ts (путь репозитория). Environment variables в Vite доступны только с префиксом VITE_ — они встраиваются в клиентский код и видны всем.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        React Strict Mode в dev вызывает двойной mount/unmount — это помогает найти missing cleanup в effects. Перед деплоем прогони Lighthouse: Performance, Accessibility, Best Practices. Escape Hatches (useEffect, useRef) — инструменты «выхода» из чистой модели React, когда нужна интеграция с браузерными API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- react.dev: Escape Hatches\n- react.dev: useEffect\n- Vite: Deploy

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: useEffect связывает React с внешним миром; production build + deploy завершают цикл от кода до живого приложения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Persist todos в localStorage через useEffect
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Загрузка начального state из localStorage (lazy init useState)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Production build, проверь размер bundle
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Задеплой на GitHub Pages или Vercel
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Финальный self-review по react.dev Quick Start checklist
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. README с live demo URL и скриншотом
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-11-done
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Todos сохраняются между сессиями

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Production build успешен

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Live demo доступен по URL

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Persist todos в localStorage через useEffect
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Загрузка начального state из localStorage (lazy init useState)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Production build, проверь размер bundle
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Задеплой на GitHub Pages или Vercel
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-11\n\ngit add .\n\ngit commit -m "week-11 day-07: persist, deploy и React Todo App"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        React Todo App — полноценное приложение на Vite + TypeScript. Подробное ТЗ: docs/projects.md — Неделя 11.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции: CRUD задач, фильтры, счётчик, localStorage, тёмная тема, адаптивная вёрстка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Добавление, toggle, удаление задач с валидацией

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Фильтры: all / active / completed + счётчик оставшихся

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Переключение светлой/тёмной темы с persist

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Адаптивная вёрстка от 320px

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] 8+ компонентов, типизированные props

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] useState + lifting state + controlled forms

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] CSS Modules или эквивалентная изоляция стилей

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] localStorage persist, deployed demo

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Lighthouse Accessibility ≥ 90

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] README с URL деплоя и инструкцией npm run dev

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тег week-11-done

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Чем JSX отличается от HTML?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Зачем нужен key в списках и почему не index?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Как обновить элемент массива в state иммутабельно?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Что такое controlled component?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Могу ли я объяснить однонаправленный поток данных в React?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **React Todo** в `learning-log/week-11/`, осмысленная Git-история, тег `week-11-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nReact: компоненты, props, state\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-11-day-1", "label": "День 1 (Mon): Введение в React и JSX"}, {"id": "week-11-day-2", "label": "День 2 (Tue): Props и композиция"}, {"id": "week-11-day-3", "label": "День 3 (Wed): Списки, keys и рендеринг"}, {"id": "week-11-day-4", "label": "День 4 (Thu): События и состояние (useState)"}, {"id": "week-11-day-5", "label": "День 5 (Fri): Формы и подъём состояния"}, {"id": "week-11-day-6", "label": "День 6 (Sat): Стилизация и структура проекта"}, {"id": "week-11-day-7", "label": "День 7 (Sun): Сборка Todo App и деплой"}, {"id": "week-11-project", "label": "Проект недели"}, {"id": "week-11-review", "label": "Ревью-чеклист"}], "text": "Неделя 11: React — компоненты, JSX, props, Vite, первые компоненты Цель недели: создать первое React-приложение на Vite, освоить компоненты, JSX, props и базовые паттерны. Литература: react.dev Learn , React TypeScript Cheatsheet , Vite Guide , Thinking in React , React — Quick Start Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-11/ День 1 (Mon): Введение в React и JSX Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к React Todo Теория React — библиотека для построения пользовательских интерфейсов на основе компонентов. Компонент — это JavaScript-функция (или класс), которая принимает props и возвращает описание UI. React берёт это опис…"} \ No newline at end of file +{"id": "week-11", "title": "React basics", "fullTitle": "Неделя 11: React — компоненты, JSX, props, Vite, первые компоненты", "html": "

                                                                                                                                                                                                                        Неделя 11: React — компоненты, JSX, props, Vite, первые компоненты

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: создать первое React-приложение на Vite, освоить компоненты, JSX, props и базовые паттерны.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература: react.dev Learn, React TypeScript Cheatsheet, Vite Guide, Thinking in React, React — Quick Start

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git: минимум 1 осмысленный коммит каждый день в learning-log/week-11/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 1 (Mon): Введение в React и JSX

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        React — библиотека для построения пользовательских интерфейсов на основе компонентов. Компонент — это JavaScript-функция (или класс), которая принимает props и возвращает описание UI. React берёт это описание и обновляет реальный DOM эффективно через Virtual DOM и reconciliation. Философия React: UI = f(state) — интерфейс является функцией от состояния.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        JSX — синтаксическое расширение, которое выглядит как HTML, но компилируется в вызовы React.createElement. Правила JSX отличаются от HTML: className вместо class, htmlFor вместо for, все теги закрываются (<img />, <br />). В фигурных скобках {expression} встраивается любое JavaScript-выражение: переменные, вызовы функций, тернарные операторы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Компоненты именуются в PascalCase (Header, TodoItem), а props — в camelCase. JSX автоматически экранирует строки — вставка пользовательского текста безопасна от XSS. Компонент должен возвращать один корневой элемент; если нужно несколько соседних без обёрточного <div>, используй Fragment: <>...</>. Не вызывай компоненты как обычные функции Header() — только через JSX <Header />, иначе React не отследит жизненный цикл и hooks.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель React — театр теней, где ты не двигаешь фигурки на экране руками (не пишешь document.querySelector и .innerHTML вручную), а просто описываешь, как должна выглядеть сцена при текущем состоянии сюжета — React сам разбирается, какие фигурки подвинуть, а какие оставить на месте. UI = f(state) означает: дай мне текущее состояние — и я построю (или перестрою) весь экран заново на бумаге (Virtual DOM), а дальше сравню с предыдущей версией и внесу в реальный DOM только конкретные изменения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Этот декларативный подход — причина, по которой почти весь современный фронтенд использует React или похожие библиотеки: он снимает с разработчика необходимость вручную отслеживать, какие части DOM устарели после изменения данных, — раньше это была одна из главных причин багов в jQuery-подобном коде. Всё, что изучалось на неделях 8–9 (async, замыкания, паттерн Observer), напрямую готовило именно к этой модели: React-компонент — это, по сути, функция, подписанная на изменения state через встроенный Observer-механизм.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение новичков — вызывать компонент как обычную функцию (Header()) вместо JSX (<Header />), особенно когда нужно «просто получить разметку». Разница критична: только вызов через JSX регистрирует компонент в дереве React с собственным местом для hooks и состояния; прямой вызов функции полностью ломает эту связь, и hooks внутри такого компонента либо упадут с ошибкой, либо будут работать непредсказуемо. Задание 3 практики («вынеси Header, Footer, Hero в отдельные файлы») стоит сразу делать с привычкой использовать JSX-синтаксис, а не вызовы функций.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- react.dev: Describing the UI\n- react.dev: Writing Markup with JSX\n- React — Quick Start

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: компонент — функция от props к UI; JSX — удобный синтаксис описания, а не HTML.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Изучи структуру Vite react-ts проекта из недели 10
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Очисти App.tsx, создай разметку лендинга в JSX
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Вынеси Header, Footer, Hero в отдельные файлы компонентов
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Используй Fragment вместо обёрточного div где возможно
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Подключи CSS-модуль или отдельный App.css
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай learning-log/week-11/ — новый Vite-проект или форк week-10
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь ESLint rules для React (eslint-plugin-react)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Минимум 3 компонента в отдельных файлах

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Корректный JSX без ошибок ESLint

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] className вместо class

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Изучи структуру Vite react-ts проекта из недели 10
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Очисти App.tsx, создай разметку лендинга в JSX
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Вынеси Header, Footer, Hero в отдельные файлы компонентов
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Используй Fragment вместо обёрточного div где возможно
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-11\n\ngit add src/components/\n\ngit commit -m "week-11 day-01: JSX, Header, Footer и Hero"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 2 (Tue): Props и композиция

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Props (properties) — единственный способ передать данные от родителя к ребёнку в React. Props read-only: дочерний компонент не должен их мутировать. Это основа однонаправленного потока данных (one-way data flow): состояние живёт выше, данные текут вниз через props, события — вверх через callback-функции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Деструктуризация в сигнатуре делает код читаемым: function Button({ label, onClick, variant = 'primary' }) вместо props.label. Значения по умолчанию задавай прямо в деструктуризации. Специальный prop children — содержимое между открывающим и закрывающим тегами: <Card>Это children</Card>. Паттерн slot: Card рендерит children внутри своей разметки, а родитель решает, что туда положить.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Spread props (<Input {...fieldProps} />) передаёт все свойства объекта разом — удобно, но осторожно: лишние props могут попасть на DOM-элемент и вызвать warning. Props drilling на 1–2 уровня — нормальная практика; Context (неделя 13+) понадобится при глубокой вложенности. В TypeScript каждый компонент получает interface XxxProps с явными типами.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель props — посылка с товаром, а не пульт дистанционного управления: родитель кладёт в посылку (props) всё, что нужно ребёнку для отображения, и отправляет её вниз, но не может через эту же посылку управлять ребёнком напрямую — единственный способ «получить обратную связь» от ребёнка — это положить в посылку функцию-callback (onClick), которую ребёнок вызовет, если что-то произойдёт. Информация всегда течёт по одному маршруту: данные — вниз, события — вверх.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эта дисциплина односторонного потока данных станет критичной уже завтра при работе со списками и на день 5 этой недели, при подъёме состояния (lifting state up): как только в приложении появляется больше двух-трёх компонентов, обменивающихся данными, любое отклонение от «props вниз, callback вверх» превращает приложение в паутину сложно отслеживаемых связей. Паттерн children — первый шаг к композиции, которая в React предпочтительнее наследования компонентов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — пытаться изменить props изнутри дочернего компонента, например props.disabled = true внутри Button: это не вызовет ошибку синтаксиса, но нарушит контракт React и приведёт к рассинхронизации между тем, что видит родитель, и тем, что реально происходит. Конкретный пример из задания 4 практики — композиция Card внутри Hero, где Hero передаёт в Card не данные напрямую, а готовый JSX через children, что позволяет Card оставаться полностью независимым от содержимого, которое в него положат.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- react.dev: Passing Props to a Component\n- react.dev: Thinking in React\n- React TypeScript Cheatsheet: Components

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: props — read-only вход компонента; данные вниз, события вверх через callbacks.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Button с props: variant: 'primary' | 'secondary', size, disabled, onClick
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Card с title, children, опциональным footer
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Avatar с src, alt, size — значения по умолчанию
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Композиция: Card внутри Hero, Button в Card.footer
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Задокументируй props через TypeScript interfaces
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Компонент Icon с name и aria-label для a11y
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Story-подобная страница: все варианты Button на одном экране
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Все props типизированы

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] children используется для композиции

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Default props через деструктуризацию

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Button с props: variant: 'primary' | 'secondary', size, disabled, onClick
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Card с title, children, опциональным footer
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Avatar с src, alt, size — значения по умолчанию
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Композиция: Card внутри Hero, Button в Card.footer
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-11\n\ngit add src/components/ui/\n\ngit commit -m "week-11 day-02: Button, Card, Avatar и композиция"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Мутация props — запрещено

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          key не доступен как prop — отдельный атрибут

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Пропуск alt на img — a11y регрессия

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 3 (Wed): Списки, keys и рендеринг

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Списки в React рендерятся через array.map(): каждый элемент массива превращается в JSX. React нужен атрибут key на элементе верхнего уровня в map — уникальный и стабильный идентификатор (обычно item.id). Key помогает reconciliation: React сопоставляет элементы между рендерами и обновляет только изменившиеся, а не пересоздаёт весь список.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Использование индекса массива как key (key={index}) допустимо только для статических списков без reorder/delete. При удалении элемента из середины индексы сдвигаются — React перепутает компоненты, и state (например, фокус input) «переедет» к другому элементу. Всегда предпочитай key={todo.id}.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Условный рендеринг: {isLoggedIn && <Dashboard />} (осторожно — 0 falsy и отрендерится как текст), тернарный {loading ? <Spinner /> : <List />}, early return if (!data) return null. Не вызывай компоненты как функции TodoItem(todo) — только <TodoItem todo={todo} />. Fragment с key нужен при map фрагментов: <Fragment key={id}>...</Fragment>.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель key — номерок в гардеробе, а не порядковое место в очереди: если ты сдал куртку под номерком 42, гардеробщик найдёт именно твою куртку, даже если перед тобой в очереди кто-то ушёл или встал новый человек — потому что номерок привязан к вещи, а не к позиции в очереди. Индекс массива в качестве key — это использование места в очереди вместо номерка: работает, пока никто не покидает очередь и не встаёт в середину, но ломается при малейшей перестановке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Правильная работа со списками и keys — база, на которой строится практически весь остаточный курс: Todo-приложение этой недели, а позже любой список карточек, комментариев или элементов меню в реальных проектах будет опираться именно на эту механику reconciliation. Ошибки с key — одна из самых частых причин странных багов вроде «текст в input переехал не в ту строку после удаления элемента», которые сложно диагностировать, не зная про reconciliation.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать warning React про отсутствующий key просто стилистической придиркой линтера, которую можно проигнорировать. Конкретный пример: список из трёх задач с controlled input для редактирования названия, где key — это index; при удалении первой задачи React решит, что вторая задача (индекс 0) заменила первую, и переиспользует её DOM-узел вместе с локальным состоянием (например, фокусом или незасабмиченным текстом в поле), хотя данные (todo.id) на самом деле принадлежат другой задаче. Задание 7 практики («проверь: удаление средней задачи не ломает state остальных») — прямая проверка именно этого сценария.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- react.dev: Rendering Lists\n- react.dev: Conditional Rendering\n- react.dev: Fragment

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: стабильный key по id — не оптимизация, а корректность при изменении порядка и удалении элементов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Компонент TodoList — рендер массива Todo[]
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. TodoItem с props: todo, onToggle, onDelete
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. keys = todo.id, не индекс массива
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Пустой список: условный рендер «Нет задач»
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Фильтр tabs: all / active / done — условное отображение
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь mock-данные в data/todos.ts — 5+ задач
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь: удаление средней задачи не ломает state остальных
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Стабильные keys на основе id

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Условный рендер для empty state

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] map возвращает JSX, не side effects

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Компонент TodoList — рендер массива Todo[]
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. TodoItem с props: todo, onToggle, onDelete
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. keys = todo.id, не индекс массива
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Пустой список: условный рендер «Нет задач»
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-11\n\ngit add src/components/todo/ src/data/\n\ngit commit -m "week-11 day-03: TodoList, keys и условный рендер"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 4 (Thu): События и состояние (useState)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Интерактивность в React начинается с useState — hook, дающий компоненту «память». const [count, setCount] = useState(0) возвращает текущее значение и функцию обновления. Вызов setCount планирует ререндер компонента с новым значением. State — это снимок на момент рендера: если вызвать setCount(count + 1) три раза подряд в одном обработчике, счётчик увеличится на 1, не на 3. Для последовательных обновлений используй функциональную форму: setCount(c => c + 1).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Обновления state должны быть иммутабельными: вместо todos.push(item) пиши setTodos([...todos, item]); вместо todo.done = truesetTodos(todos.map(t => t.id === id ? { ...t, done: true } : t)). React сравнивает ссылки — мутация не вызовет ререндер. Controlled input связывает <input value={text} onChange={e => setText(e.target.value)} /> — React state единственный источник правды для значения поля.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Несколько useState предпочтительнее одного большого объекта state — проще обновлять отдельные поля. Derived values (счётчик активных задач) вычисляй из state при рендере, а не храни в отдельном useState. Batching: React объединяет несколько setState в одном обработчике события в один ререндер.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель useState — стикер на холодильнике, который React перечитывает перед каждым рендером, а не переменная, которую можно менять на лету: вызов setCount(5) не меняет count немедленно в текущей функции — он говорит React «на следующем рендере напиши на стикере 5», и только тогда компонент увидит новое значение. Именно поэтому console.log(count) сразу после setCount(count + 1) в том же обработчике покажет старое значение — стикер ещё не переписан.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Иммутабельные обновления state — не просто стилистическая рекомендация, а требование механизма React: reconciliation (день 3 этой недели) сравнивает ссылки на объекты между рендерами для оптимизации, и мутация todo.done = true не создаёт новую ссылку, поэтому React может решить, что ничего не изменилось, и пропустить ререндер, оставив UI визуально устаревшим при внутренне изменённых данных. Этот же принцип иммутабельности потребуется в Redux, Zustand и других state-менеджерах, которые встретятся дальше в карьере.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что несколько вызовов setState в одном обработчике происходят мгновенно и последовательно: setCount(count + 1); setCount(count + 1); setCount(count + 1) при count = 0 даст count = 1, а не 3, потому что все три вызова читают одно и то же значение count из замыкания текущего рендера (см. неделю 9 про замыкания — прямое применение той темы). Чтобы получить 3, нужна функциональная форма: setCount(c => c + 1) трижды — каждый вызов получает актуальное промежуточное значение. Это ключевая проверка в задании 1 практики («счётчик с useState»).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- react.dev: State: A Component's Memory\n- react.dev: Adding Interactivity\n- react.dev: Queueing a Series of State Updates

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: state обновляй иммутабельно; функциональный апдейт setX(x => ...) даёт актуальное значение при batching.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Счётчик в Hero с useState
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Controlled input: value + onChange для поля новой задачи
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавление задачи в массив через immutable update
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Toggle done: todos.map(t => t.id === id ? {...t, done: !t.done} : t)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Удаление через filter
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Счётчик «активных» задач — derived из state, не отдельный useState
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Добавь createdAt: Date.now() при создании задачи
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Все inputs controlled

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] State обновляется иммутабельно

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет прямой мутации массива todos

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Счётчик в Hero с useState
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Controlled input: value + onChange для поля новой задачи
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавление задачи в массив через immutable update
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Toggle done: todos.map(t => t.id === id ? {...t, done: !t.done} : t)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-11\n\ngit add src/components/todo/\n\ngit commit -m "week-11 day-04: useState, CRUD задач и controlled input"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 5 (Fri): Формы и подъём состояния

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Формы в React обрабатываются через событие onSubmit на <form> с обязательным e.preventDefault() — иначе браузер перезагрузит страницу. Подъём состояния (lifting state up) — ключевой паттерн: если два компонента (TodoList и FilterTabs) должны разделять данные, state поднимается к их ближайшему общему родителю (TodoApp). Родитель хранит todos и filter, детям передаёт данные и колбэки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Controlled components — стандарт для форм: значение input, textarea, select и checkbox полностью управляется React state. Uncontrolled (через ref) допустим для простых случаев, но controlled даёт полный контроль: валидация, disabled, сброс. Колбэки вниз: onToggle(id), onDelete(id), onFilterChange('active') — дочерний компонент сообщает родителю о действии, не меняя state напрямую.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Валидация на клиенте: проверяй перед submit (пустая задача не добавляется), показывай ошибку рядом с полем. Атрибут name на input важен для autofill и семантики. Disabled кнопка submit при невалидной форме — простая и эффективная UX-защита. Enter в поле ввода сабмитит форму, если input внутри <form>.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель подъёма состояния — общий банковский счёт семьи вместо отдельных кошельков у каждого члена: если TodoList и FilterTabs хранили бы каждый свою копию списка задач или фильтра, они быстро разошлись бы в показаниях; подняв единственный «счёт» (state) к общему родителю TodoApp, оба компонента всегда видят одни и те же актуальные данные, просто получают их сверху как props.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Этот принцип — прямое следствие однонаправленного потока данных, изученного в день 2, и он же причина, по которой в больших приложениях появляются глобальные хранилища состояния (Context API, Redux, Zustand — темы будущих недель): по сути, они автоматизируют «подъём состояния» до уровня всего приложения, когда общий родитель для двух компонентов оказывается слишком далеко в дереве. Понимание lifting state up вручную — обязательный шаг перед тем, как эти инструменты станут осмысленными, а не «магическими коробками».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — забывать e.preventDefault() в обработчике onSubmit: без него браузер выполнит свою родную логику отправки формы — полную перезагрузку страницы, — и весь React state приложения сбросится, будто страница открыта заново. Конкретный пример из задания 2 практики: AddTodoForm должен не просто добавить задачу в массив, но и явно очистить своё поле ввода после сабмита — если это забыть, React аккуратно оставит в controlled input то значение, что было до сабмита, ведь состояние поля никто не сбросил.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- react.dev: Reacting to Input with State\n- react.dev: Sharing State Between Components\n- react.dev: Form

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: общий state — у ближайшего общего родителя; форма controlled, события — через callbacks вверх.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. TodoApp — state todos, filter наверху
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. AddTodoForm — submit добавляет задачу, очищает input
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. FilterTabs — подними filter state, передай setFilter
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. TodoStats — вычисляемые значения из props (active count)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Валидация: пустая задача не добавляется, показ ошибки
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. AddTodoForm — disabled кнопка при пустом поле
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Enter в поле ввода сабмитит форму
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] State в общем родителе TodoApp

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Форма с preventDefault

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Валидация пустого ввода

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. TodoApp — state todos, filter наверху
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. AddTodoForm — submit добавляет задачу, очищает input
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. FilterTabs — подними filter state, передай setFilter
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. TodoStats — вычисляемые значения из props (active count)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-11\n\ngit add src/components/todo/TodoApp.tsx\n\ngit commit -m "week-11 day-05: lifting state, форма и фильтры"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 6 (Sat): Стилизация и структура проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Стилизация React-приложения начинается с организации, а не с выбора CSS-in-JS библиотеки. CSS Modules изолируют стили: import styles from './Button.module.css' и className={styles.primary} — классы уникальны на уровне файла, нет конфликтов имён. Условные классы удобно собирать через template literal или утилиту cn(...classes), которая фильтрует falsy-значения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура src/ по назначению: components/ui/ — переиспользуемые (Button, Card), components/todo/ — предметные, types/ — TypeScript-интерфейсы, hooks/ — custom hooks (позже), utils/ — чистые функции, data/ — mock-данные. Vite позволяет импортировать изображения как модули: import logo from './logo.svg' — URL подставится автоматически.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тёмная тема через CSS variables: в :root задай --bg: #fff; --text: #111, в .dark переопредели --bg: #111; --text: #fff. Переключение — class на <html> или корневом div, управляемый React state. prefers-color-scheme: dark в media query задаёт системную тему по умолчанию. Mobile-first: базовые стили для узкого экрана, @media (min-width: 768px) для расширения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель CSS Modules — именные бейджи на конференции вместо простых имён на футболке: класс .primary в обычном CSS — это имя на футболке, которое может совпасть у двух незнакомых людей (двух компонентов) и вызвать путаницу (конфликт стилей); CSS Modules автоматически превращают .primary в уникальный .Button_primary__a3f9k, как персональный бейдж с номером — конфликт физически невозможен, даже если два файла независимо используют одно и то же короткое имя класса.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Продуманная структура папок (components/ui/, components/todo/, types/, hooks/, utils/) — не бюрократия, а прямая подготовка к росту проекта: как только в приложении становится больше 15–20 компонентов, плоская структура файлов в одной папке превращается в неразбираемый список, и рефакторинг структуры «на живую» гораздо дороже, чем следование конвенции с самого начала. CSS variables для темы — тот же принцип, что и useState для данных: единый источник истины (--bg, --text), который меняется в одном месте и автоматически применяется везде, где используется.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — реализовывать тёмную тему через дублирование всех компонентов или инлайновые проверки isDark ? '#111' : '#fff' в каждом месте, где нужен цвет: это плохо масштабируется и легко забыть при добавлении нового компонента. Конкретный пример из задания 5 практики: одна строка document.documentElement.classList.toggle('dark') вместе с заранее описанными CSS-переменными в :root и .dark переключает весь интерфейс разом, без единого условия внутри JSX компонентов — вся логика темы живёт в CSS, а React лишь переключает один класс.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Vite: Static Assets\n- CSS Modules — spec\n- MDN: CSS custom properties

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: CSS Modules + логичная структура папок + CSS variables для темы — достаточный фундамент без CSS-in-JS.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. CSS Modules для Button, Card, TodoItem
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Утилита cn(...classes) для объединения классов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Реорганизуй src: components/todo/, components/ui/
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Перенеси типы в types/todo.ts, mock data в data/
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Тёмная тема через class на root + CSS variables
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Адаптив: mobile-first для TodoApp (min-width breakpoints)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь контраст текста в обеих темах
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Логичная структура папок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] CSS Modules без глобальных конфликтов

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тема переключается через state + class

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. CSS Modules для Button, Card, TodoItem
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Утилита cn(...classes) для объединения классов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Реорганизуй src: components/todo/, components/ui/
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Перенеси типы в types/todo.ts, mock data в data/
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-11\n\ngit add src/ src/**/*.module.css\n\ngit commit -m "week-11 day-06: CSS Modules, структура и тёмная тема"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 7 (Sun): Сборка Todo App и деплой

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Завершение Todo App объединяет state, effects и production-сборку. useEffect — hook для синхронизации React state с внешним миром (localStorage, document.title, подписки). Для persist: useEffect(() => { localStorage.setItem('todos', JSON.stringify(todos)) }, [todos]) — сохраняй при каждом изменении. Начальное значение загружай через lazy init: useState(() => JSON.parse(localStorage.getItem('todos') ?? '[]')).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Production-сборка: npm run build создаёт оптимизированный bundle в dist/, npm run preview проверяет его локально. Деплой на GitHub Pages, Netlify или Vercel — статический хостинг для SPA. Для GitHub Pages задай base в vite.config.ts (путь репозитория). Environment variables в Vite доступны только с префиксом VITE_ — они встраиваются в клиентский код и видны всем.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        React Strict Mode в dev вызывает двойной mount/unmount — это помогает найти missing cleanup в effects. Перед деплоем прогони Lighthouse: Performance, Accessibility, Best Practices. Escape Hatches (useEffect, useRef) — инструменты «выхода» из чистой модели React, когда нужна интеграция с браузерными API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель useEffect — розетка, через которую компонент подключается к внешнему миру за пределами React (браузерное API, таймер, подписка, localStorage): React сам управляет своим внутренним миром (state, JSX), но для всего, что находится снаружи этой модели, нужен явный «провод» — эффект, который запускается после рендера и должен уметь отключиться (cleanup-функция), когда компонент размонтируется или зависимости меняются, — иначе розетка останется под напряжением без нужды (утечка памяти, лишние подписки).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эта неделя завершает связку тем всего курса: async/await и Promise (неделя 8) применяются внутри useEffect для загрузки данных, замыкания (неделя 9) объясняют, почему эффект «видит» устаревшее значение state, если забыть указать зависимость в массиве [todos], а TypeScript (неделя 10) типизирует и сам todos, и то, что приходит из localStorage.getItem(). Деплой — финальный шаг, превращающий учебный проект в то, что можно показать в резюме и на собеседовании по ссылке, а не только скриншотом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — использовать обычный useState(JSON.parse(localStorage.getItem('todos') ?? '[]')) без функции-инициализатора: такая запись выполняет JSON.parse и чтение localStorage при каждом рендере компонента, а не только при первом монтировании, что зря тратит ресурсы на большом списке задач. Ленивая инициализация useState(() => JSON.parse(...)) передаёт функцию, а не результат её вызова — React выполнит её ровно один раз, при первом рендере. Это стоит явно проверить в задании 2 практики дня, добавив временный console.log внутрь инициализатора и посчитав, сколько раз он сработает при обычном использовании приложения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- react.dev: Escape Hatches\n- react.dev: useEffect\n- Vite: Deploy

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: useEffect связывает React с внешним миром; production build + deploy завершают цикл от кода до живого приложения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Persist todos в localStorage через useEffect
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Загрузка начального state из localStorage (lazy init useState)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Production build, проверь размер bundle
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Задеплой на GitHub Pages или Vercel
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Финальный self-review по react.dev Quick Start checklist
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. README с live demo URL и скриншотом
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-11-done
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Todos сохраняются между сессиями

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Production build успешен

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Live demo доступен по URL

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Persist todos в localStorage через useEffect
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Загрузка начального state из localStorage (lazy init useState)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Production build, проверь размер bundle
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Задеплой на GitHub Pages или Vercel
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-11\n\ngit add .\n\ngit commit -m "week-11 day-07: persist, deploy и React Todo App"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        React Todo App — полноценное приложение на Vite + TypeScript. Подробное ТЗ: docs/projects.md — Неделя 11.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции: CRUD задач, фильтры, счётчик, localStorage, тёмная тема, адаптивная вёрстка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Добавление, toggle, удаление задач с валидацией

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Фильтры: all / active / completed + счётчик оставшихся

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Переключение светлой/тёмной темы с persist

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Адаптивная вёрстка от 320px

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] 8+ компонентов, типизированные props

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] useState + lifting state + controlled forms

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] CSS Modules или эквивалентная изоляция стилей

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] localStorage persist, deployed demo

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Lighthouse Accessibility ≥ 90

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] README с URL деплоя и инструкцией npm run dev

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тег week-11-done

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Чем JSX отличается от HTML?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Зачем нужен key в списках и почему не index?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Как обновить элемент массива в state иммутабельно?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Что такое controlled component?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Могу ли я объяснить однонаправленный поток данных в React?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **React Todo** в `learning-log/week-11/`, осмысленная Git-история, тег `week-11-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nReact: компоненты, props, state\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-11-day-1", "label": "День 1 (Mon): Введение в React и JSX"}, {"id": "week-11-day-2", "label": "День 2 (Tue): Props и композиция"}, {"id": "week-11-day-3", "label": "День 3 (Wed): Списки, keys и рендеринг"}, {"id": "week-11-day-4", "label": "День 4 (Thu): События и состояние (useState)"}, {"id": "week-11-day-5", "label": "День 5 (Fri): Формы и подъём состояния"}, {"id": "week-11-day-6", "label": "День 6 (Sat): Стилизация и структура проекта"}, {"id": "week-11-day-7", "label": "День 7 (Sun): Сборка Todo App и деплой"}, {"id": "week-11-project", "label": "Проект недели"}, {"id": "week-11-review", "label": "Ревью-чеклист"}], "text": "Неделя 11: React — компоненты, JSX, props, Vite, первые компоненты Цель недели: создать первое React-приложение на Vite, освоить компоненты, JSX, props и базовые паттерны. Литература: react.dev Learn , React TypeScript Cheatsheet , Vite Guide , Thinking in React , React — Quick Start Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-11/ День 1 (Mon): Введение в React и JSX Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к React Todo Теория React — библиотека для построения пользовательских интерфейсов на основе компонентов. Компонент — это JavaScript-функция (или класс), которая принимает props и возвращает описание UI. React берёт это опис…"} \ No newline at end of file diff --git a/docs/weeks/12.json b/docs/weeks/12.json index 3619272..e069ba5 100644 --- a/docs/weeks/12.json +++ b/docs/weeks/12.json @@ -1 +1 @@ -{"id": "week-12", "title": "React state", "fullTitle": "Неделя 12: React — state, эффекты, формы", "html": "

                                                                                                                                                                                                                        Неделя 12: React — state, эффекты, формы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: научиться управлять состоянием компонентов, побочными эффектами и формами в React.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература: react.dev — Learn, React — State, React — Effects, You Might Not Need an Effect, React — Forms

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git: минимум 1 осмысленный коммит каждый день в learning-log/week-12/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 78 (Пн): useState — память компонента

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo Pro

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        useState — фундаментальный hook React, дающий функциональному компоненту локальное состояние. При первом рендере React создаёт ячейку state; при последующих — возвращает сохранённое значение. setState не меняет переменную мгновенно — он планирует ререндер с новым значением. Поэтому console.log(count) сразу после setCount(5) покажет старое значение.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Иммутабельные обновления обязательны: [...arr, item] для добавления, arr.filter(...) для удаления, arr.map(...) для изменения элемента. Прямая мутация (arr.push, obj.field = x) не вызовет ререндер, потому что ссылка на объект не изменилась. Lazy initialization useState(() => expensiveCalc()) вычисляет начальное значение только при первом рендере — важно для чтения localStorage.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функциональный апдейт setCount(c => c + 1) получает актуальное значение из очереди обновлений. Три таких вызова подряд дадут +3, в отличие от setCount(count + 1). State изолирован между экземплярами: два <Counter /> на странице имеют независимые счётчики. Несколько useState лучше одного объекта — проще обновлять и меньше риск случайной мутации.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- useState\n- react.dev: State: A Component's Memory\n- react.dev: Queueing a Series of State Updates

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: state — снимок на рендер; обновляй иммутабельно и используй функциональный апдейт при последовательных изменениях.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай Vite-проект: npm create vite@latest week-12 -- --template react-ts в learning-log/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Компонент Counter с кнопками +1, -1, Сброс
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Компонент ColorPicker — state цвета фона, кнопки переключения темы
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Счётчик кликов в App, передавай count и setCount в дочерний компонент
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Демонстрация функционального апдейта: три setCount(c => c + 1) подряд
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Lazy init: useState(() => JSON.parse(localStorage.getItem('x') ?? '0'))
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Раздели сложный state на несколько useState
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет прямой мутации state (arr.push без копии)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Каждый компонент в отдельном файле

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] DevTools React показывает обновления state

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай Vite-проект: npm create vite@latest week-12 -- --template react-ts в learning-log/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Компонент Counter с кнопками +1, -1, Сброс
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Компонент ColorPicker — state цвета фона, кнопки переключения темы
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Счётчик кликов в App, передавай count и setCount в дочерний компонент
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-12\n\ngit add src/components/Counter.tsx src/components/ColorPicker.tsx\n\ngit commit -m "week-12 day-78: useState, Counter и ColorPicker"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Мутация объекта/массива напрямую — UI не обновится

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Вызов setCount(count + 1) три раза подряд в одном обработчике даёт +1, не +3 — используй функциональный апдейт

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 79 (Вт): События и controlled components

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo Pro

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Обработка событий в React похожа на DOM, но есть отличия. Атрибуты пишутся в camelCase: onClick, onChange, onSubmit. React использует Synthetic Events — обёртку над нативными событиями с единым API и пулингом для производительности. e.preventDefault() отменяет действие по умолчанию (перезагрузка формы), e.stopPropagation() останавливает всплытие.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Controlled component — input, значение которого полностью контролируется React state. Для text input: value={text} + onChange={e => setText(e.target.value)}. Для checkbox: checked={done} + onChange, не value. Для select: value={priority} на <select>, не selected на <option>. Группа radio: один state, разные value у <input type=\"radio\">.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Разница readOnly и disabled: disabled элемент не участвует в tab-навигации и не отправляется с формой; readOnly виден и фокусируем, но не редактируется. defaultValue вместо value делает компонент uncontrolled — React не управляет значением после первого рендера. Для форм с валидацией и сбросом предпочитай controlled.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- React — Responding to Events\n- React — Forms\n- react.dev: Controlled vs Uncontrolled

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: controlled input = React state единственный источник правды; value + onChange для каждого поля.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши Todo App (vanilla JS) на React с useState
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Поля: добавление задачи, чекбокс «выполнено», удаление
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Фильтр: All / Active / Completed — отдельный state filter
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Счётчик активных задач в шапке
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Textarea для описания задачи — controlled
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Select приоритета: low / medium / high
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь tab-навигацию по всем полям формы
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Input полностью controlled

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] onSubmit формы с preventDefault

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Фильтрация не мутирует исходный массив

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши Todo App (vanilla JS) на React с useState
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Поля: добавление задачи, чекбокс «выполнено», удаление
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Фильтр: All / Active / Completed — отдельный state filter
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Счётчик активных задач в шапке
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-12\n\ngit add src/components/todo/\n\ngit commit -m "week-12 day-79: controlled inputs и Todo на React"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          defaultValue вместо value — компонент становится uncontrolled

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Забытый key при рендере списка задач — баги при удалении

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 80 (Ср): useEffect — побочные эффекты

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo Pro

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        useEffect синхронизирует React-компонент с внешними системами: DOM API, таймеры, подписки, fetch, localStorage. Сигнатура: useEffect(() => { /* effect */ return () => { /* cleanup */ }; }, [deps]). Пустой массив deps [] — effect выполнится один раз при mount (аналог componentDidMount). [dep] — при изменении dep. Без массива deps — при каждом рендере (почти всегда ошибка).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Cleanup function вызывается перед повторным effect и при unmount: отписка от событий, очистка таймера, abort fetch. Без cleanup — утечки памяти и warnings. React Strict Mode в dev намеренно mount → unmount → mount, чтобы выявить missing cleanup.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не всё требует effect. You Might Not Need an Effect: вычисление derived state, обработка клика, валидация формы — это event handlers, не effects. Effect — для синхронизации с внешним миром, когда нет события-повода. Stale closure — классический баг: effect с [] использует устаревший props/state; добавь их в deps. useLayoutEffect выполняется синхронно после DOM-мутаций, до paint — для измерений layout (обзор).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- useEffect\n- You Might Not Need an Effect\n- react.dev: Synchronizing with Effects

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: useEffect — для синхронизации с внешним миром; cleanup обязателен; не дублируй логику обработчиков событий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. DocumentTitle — меняет document.title при смене страницы/задачи
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Таймер Pomodoro: 25 мин countdown, cleanup при unmount
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. useEffect с localStorage: загрузка при mount, сохранение при изменении todos
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Нарисуй схему: render → effect → cleanup → re-render
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Подписка на window.resize с cleanup removeEventListener
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Исправь намеренно сломанный effect с missing deps
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Рефакторинг: убери лишний effect, перенеси логику в обработчик
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Таймер очищается при размонтировании

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Зависимости effect указаны корректно (ESLint react-hooks)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет бесконечного цикла effect → setState → effect

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. DocumentTitle — меняет document.title при смене страницы/задачи
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Таймер Pomodoro: 25 мин countdown, cleanup при unmount
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. useEffect с localStorage: загрузка при mount, сохранение при изменении todos
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Нарисуй схему: render → effect → cleanup → re-render
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-12\n\ngit add src/hooks/ src/components/DocumentTitle.tsx\n\ngit commit -m "week-12 day-80: useEffect, Pomodoro и localStorage sync"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Пустой [] при использовании props/state внутри — stale closure

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Effect без deps при каждом рендере — лишние запросы и лаги

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 81 (Чт): Fetch и паттерн loading/error/data

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo Pro

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Загрузка данных в React-компоненте — классический сценарий для useEffect + fetch. Паттерн трёх (или четырёх) состояний: loadingsuccess / error / empty. Реализуй через отдельные useState или discriminated union: { status: 'loading' } | { status: 'error', error: string } | { status: 'success', data: T }. UI рендерит разную разметку в зависимости от status.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        В effect: fetch(url).then(res => { if (!res.ok) throw new Error(); return res.json() }).then(setData).catch(setError).finally(() => setLoading(false)). Fetch не reject на HTTP 404 — проверяй res.ok. Race condition: пользователь быстро переключает id, старый ответ приходит последним. Решение — AbortController в cleanup: const ctrl = new AbortController(); fetch(url, { signal: ctrl.signal }); return () => ctrl.abort().

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не вызывай setState на размонтированном компоненте — abort или флаг let cancelled = false в cleanup. Custom hook useFetch<T>(url) инкапсулирует весь паттерн: loading, error, data, refetch. Skeleton UI вместо пустого экрана улучшает perceived performance.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Fetch API\n- MDN: AbortController\n- JSONPlaceholder

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: fetch в effect требует loading/error states, проверки res.ok, abort в cleanup и защиты от race condition.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Компонент PostList — GET /posts, спиннер при загрузке
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Обработка ошибки сети — блок с кнопкой «Повторить»
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. PostDetail — загрузка /posts/:id по клику
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Skeleton-заглушки вместо пустого экрана
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. AbortController в cleanup при смене id или unmount
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Вынеси логику в useFetch<T>(url)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Empty state: «Постов не найдено» при пустом массиве
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] AbortController в cleanup effect

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] UI для loading, error, empty, success

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет setState на размонтированном компоненте

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Компонент PostList — GET /posts, спиннер при загрузке
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Обработка ошибки сети — блок с кнопкой «Повторить»
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. PostDetail — загрузка /posts/:id по клику
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Skeleton-заглушки вместо пустого экрана
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-12\n\ngit add src/hooks/useFetch.ts src/components/PostList.tsx\n\ngit commit -m "week-12 day-81: fetch, loading/error/data и useFetch"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Забытый cleanup → warning «Can't perform state update on unmounted component»

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Race condition: старый запрос перезаписывает новый — используй abort или id запроса

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 82 (Пт): Формы в React

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo Pro

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Формы в React строятся на controlled components: каждое поле связано с state. Для формы из нескольких полей два подхода: отдельный useState на поле (проще для маленьких форм) или один объект const [form, setForm] = useState({ name: '', email: '' }) с обновлением setForm(f => ({ ...f, name: e.target.value })). Второй удобен для submit целиком и сброса.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Валидация на клиенте: required, minLength, regex для email, кастомные правила (пароль ≥ 8 символов). UX-паттерн touched/dirty: показывай ошибки после blur или submit, не при первом символе — это меньше раздражает. useId() генерирует стабильный уникальный id для связки <label htmlFor={id}> и <input id={id}> — важно для accessibility.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Сброс формы: верни state к начальным значениям. noValidate на <form> отключает браузерную валидацию, если реализуешь свою. Checkbox «согласен с условиями» — отдельный boolean state, блокирующий submit. React 19 Form Actions (обзор) упрощают submit через action prop, но controlled подход остаётся фундаментом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- React — Forms\n- React — input\n- useId

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: форма = набор controlled fields + валидация + сброс state; ошибки показывай после blur/submit, не мгновенно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Форма регистрации: имя, email, пароль, роль (select)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Валидация перед submit: email формат, пароль ≥ 8 символов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Ошибки под полями, disabled кнопка при невалидной форме
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. После успешного submit — очистка формы и toast-сообщение
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Checkbox «согласен с условиями» — обязательный для submit
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Показ/скрытие пароля кнопкой-иконкой
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. useId() для всех label/input пар
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Все поля controlled

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Ошибки показываются только после blur или submit

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] type=\"password\" и autoComplete настроены

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Форма регистрации: имя, email, пароль, роль (select)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Валидация перед submit: email формат, пароль ≥ 8 символов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Ошибки под полями, disabled кнопка при невалидной форме
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. После успешного submit — очистка формы и toast-сообщение
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-12\n\ngit add src/components/RegisterForm.tsx\n\ngit commit -m "week-12 day-82: форма регистрации и валидация"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          onChange на checkbox без checked={} — неконтролируемый чекбокс

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Валидация только на submit без UX-подсказок — плохой UX

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 83 (Сб): Подъём state (lifting state up)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo Pro

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Lifting state up (подъём состояния) решает задачу, когда два или более компонента должны отображать или изменять одни данные. State перемещается к ближайшему общему родителю. Родитель хранит данные и передаёт вниз через props; дети сообщают об изменениях через callback props (onSearchChange, onSortChange). Siblings никогда не общаются напрямую — только через родителя.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Derived state — значения, вычисляемые из props или state при рендере: const filtered = items.filter(i => i.title.includes(query)). Не дублируй их в отдельном useState — иначе рассинхрон при обновлении источника. Prop drilling на 1–2 уровня — нормально; при глубокой вложенности (неделя 13) поможет Context.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Container/Presentational split: «умный» компонент управляет state и логикой, «глупый» — только рендерит по props. useMemo (preview) кэширует результат дорогой фильтрации: useMemo(() => items.filter(...), [items, query]) — пересчёт только при изменении deps. Для 10 элементов не нужен; для 1000+ — заметная оптимизация.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Sharing State Between Components\n- react.dev: Extracting State Logic into a Reducer — preview\n- useMemo

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: общий state — у ближайшего родителя; derived values вычисляй, не дублируй в useState.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. FilterableList: родитель хранит items + searchQuery
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. SearchBar — только input, вызывает onSearchChange
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. ItemList — получает отфильтрованный массив, рендерит список
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. ItemCount — показывает «Найдено: N из M»
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Добавь сортировку (A–Z / Z–A) — ещё один поднятый state
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Вынеси фильтрацию в useMemo при 100+ элементах (mock)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Рефакторинг Todo: filter + search в одном родителе
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] SearchBar не знает про items — только про query

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Фильтрация в родителе или через useMemo

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет дублирования state в siblings

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. FilterableList: родитель хранит items + searchQuery
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. SearchBar — только input, вызывает onSearchChange
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. ItemList — получает отфильтрованный массив, рендерит список
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. ItemCount — показывает «Найдено: N из M»
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-12\n\ngit add src/components/FilterableList/\n\ngit commit -m "week-12 day-83: lifting state, FilterableList и сортировка"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Дублирование одного state в двух дочерних компонентах — рассинхрон

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Слишком глубокий drilling — пока терпимо, Context на неделе 13

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 84 (Вс): Ревью и углубление

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo Pro

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью недели — время закрепить правила hooks и подготовиться к React Todo Pro. Правила hooks: вызывай только на верхнем уровне (не в if/for) и только в React-функциях (компонентах или custom hooks). Нарушение ломает порядок hooks между рендерами. Custom hook — функция useTodos(), внутри которой useState + handlers; компонент остаётся тонким, логика переиспользуема.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        React DevTools показывают дерево компонентов, props и state в реальном времени — незаменимый инструмент отладки. ESLint react-hooks/exhaustive-deps предупреждает о missing dependencies в useEffect — не отключай правило без веской причины и комментария. Strict Mode двойной mount — норма в dev, не баг.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Чеклист code review: state обновляется иммутабельно, effects имеют cleanup, inputs controlled, deps корректны, нет setState на unmounted компоненте. Конспект «useState vs useEffect»: state — для данных UI, effect — для синхронизации с внешним миром. Подготовка к Todo Pro: приоритеты, дедлайны, Quotable API — всё на базе изученных паттернов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- React DevTools\n- Rules of Hooks\n- React Strict Mode

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: custom hooks выносят логику из компонентов; правила hooks и exhaustive-deps — страховка от типичных багов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди React Tutorial — Tic-Tac-Toe до конца
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рефакторинг Todo App: вынеси логику в useTodos (заготовка под custom hook)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Code review своего кода: immutability, deps, cleanup
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Начни скелет React Todo Pro — типы с priority и deadline
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Конспект «useState vs useEffect — когда что» на 1 страницу
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Прогони ESLint без warnings
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-12-done после финальной сборки
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Tic-Tac-Toe работает с историей ходов

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] ESLint react-hooks/exhaustive-deps без warnings

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Конспект «useState vs useEffect — когда что» на 1 страницу

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди React Tutorial — Tic-Tac-Toe до конца
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рефакторинг Todo App: вынеси логику в useTodos (заготовка под custom hook)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Code review своего кода: immutability, deps, cleanup
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Начни скелет React Todo Pro — типы с priority и deadline
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-12\n\ngit add .\n\ngit commit -m "week-12 day-84: useTodos, Tic-Tac-Toe и React Todo Pro скелет"\n\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        React Todo Pro — полнофункциональное приложение задач. Подробное ТЗ: docs/projects.md — Неделя 12.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. \n

                                                                                                                                                                                                                          CRUD задач с приоритетом (low/medium/high) и дедлайном

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. \n

                                                                                                                                                                                                                          Фильтры: статус, приоритет, поиск по тексту

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. \n

                                                                                                                                                                                                                          Persist в localStorage через useEffect

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. \n

                                                                                                                                                                                                                          Загрузка «мотивационной цитаты» с Quotable API

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. \n

                                                                                                                                                                                                                          Адаптивная вёрстка, тёмная тема через CSS-переменные

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] useState + useEffect без антипаттернов

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Controlled форма добавления задачи

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Lifting state: фильтры и список согласованы

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Quotable API с loading/error states

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Custom hook useTodos для логики CRUD

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] README с инструкцией запуска

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тег week-12-done

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Могу объяснить, почему setState асинхронный и что такое batching?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Чем controlled отличается от uncontrolled input?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Зачем cleanup в useEffect? Приведи 2 примера.

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Когда поднимать state, а когда оставить локальным?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Что произойдёт, если мутировать массив в state напрямую?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **React Todo Pro** в `learning-log/week-12/`, осмысленная Git-история, тег `week-12-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nReact hooks, effects, формы\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-12-day-78", "label": "День 78 (Пн): useState — память компонента"}, {"id": "week-12-day-79", "label": "День 79 (Вт): События и controlled components"}, {"id": "week-12-day-80", "label": "День 80 (Ср): useEffect — побочные эффекты"}, {"id": "week-12-day-81", "label": "День 81 (Чт): Fetch и паттерн loading/error/data"}, {"id": "week-12-day-82", "label": "День 82 (Пт): Формы в React"}, {"id": "week-12-day-83", "label": "День 83 (Сб): Подъём state (lifting state up)"}, {"id": "week-12-day-84", "label": "День 84 (Вс): Ревью и углубление"}, {"id": "week-12-project", "label": "Проект недели"}, {"id": "week-12-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-12-review", "label": "Проверь себя"}], "text": "Неделя 12: React — state, эффекты, формы Цель недели: научиться управлять состоянием компонентов, побочными эффектами и формами в React. Литература: react.dev — Learn , React — State , React — Effects , You Might Not Need an Effect , React — Forms Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-12/ День 78 (Пн): useState — память компонента Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к React Todo Pro Теория useState — фундаментальный hook React, дающий функциональному компоненту локальное состояние. При первом рендере React создаёт ячейку state; при последующих — возвращает сохранённое значение. setState не меняет переменную мгновенно…"} \ No newline at end of file +{"id": "week-12", "title": "React state", "fullTitle": "Неделя 12: React — state, эффекты, формы", "html": "

                                                                                                                                                                                                                        Неделя 12: React — state, эффекты, формы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: научиться управлять состоянием компонентов, побочными эффектами и формами в React.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература: react.dev — Learn, React — State, React — Effects, You Might Not Need an Effect, React — Forms

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git: минимум 1 осмысленный коммит каждый день в learning-log/week-12/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 78 (Пн): useState — память компонента

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo Pro

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        useState — фундаментальный hook React, дающий функциональному компоненту локальное состояние. При первом рендере React создаёт ячейку state; при последующих — возвращает сохранённое значение. setState не меняет переменную мгновенно — он планирует ререндер с новым значением. Поэтому console.log(count) сразу после setCount(5) покажет старое значение.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Иммутабельные обновления обязательны: [...arr, item] для добавления, arr.filter(...) для удаления, arr.map(...) для изменения элемента. Прямая мутация (arr.push, obj.field = x) не вызовет ререндер, потому что ссылка на объект не изменилась. Lazy initialization useState(() => expensiveCalc()) вычисляет начальное значение только при первом рендере — важно для чтения localStorage.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функциональный апдейт setCount(c => c + 1) получает актуальное значение из очереди обновлений. Три таких вызова подряд дадут +3, в отличие от setCount(count + 1). State изолирован между экземплярами: два <Counter /> на странице имеют независимые счётчики. Несколько useState лучше одного объекта — проще обновлять и меньше риск случайной мутации.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Полезная мысленная модель: state — это не «переменная», а ячейка в скрытой памяти React, привязанная к позиции компонента в дереве рендеринга. Каждый рендер — это функция, вызванная заново, и все обычные переменные внутри неё создаются с нуля; только то, что явно объявлено через useState, «выживает» между вызовами. Отсюда и правило: count внутри тела компонента — это константа для конкретного рендера, «снимок» на момент вызова, а не текущее значение в реальном времени.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это фундамент для всего, что будет дальше: useReducer, Context, внешние стейт-менеджеры (Redux, Zustand) — все они держатся на той же идее иммутабельных обновлений и рендера как чистой функции от state. Пример: если реализовать историю кликов через setHistory(h => [...h, Date.now()]), каждый вызов добавляет новый элемент, не трогая старые — из истории потом легко построить график или отменить последнее действие (undo), потому что прошлые снимки не испорчены мутацией.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение новичков — считать, что setCount меняет count «здесь и сейчас», как обычное присваивание в императивном коде. На самом деле React только помечает компонент как «грязный» и планирует повторный вызов функции-компонента с новым значением; до этого момента в замыкании текущего обработчика count остаётся старым. Это объясняет, почему setCount(count + 1), вызванный трижды подряд в одном обработчике, использует одно и то же устаревшее значение count из замыкания — отсюда и важность функционального апдейта setCount(c => c + 1), который получает свежее значение из очереди, а не из замыкания.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        На практике этого дня именно эта модель объясняет, почему Counter с тремя быстрыми кликами не «теряет» события, а ColorPicker корректно переключает тему даже при частых кликах — React гарантированно обработает каждое обновление очереди, даже если промежуточные значения не видны сразу в коде.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- useState\n- react.dev: State: A Component's Memory\n- react.dev: Queueing a Series of State Updates

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: state — снимок на рендер; обновляй иммутабельно и используй функциональный апдейт при последовательных изменениях.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай Vite-проект: npm create vite@latest week-12 -- --template react-ts в learning-log/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Компонент Counter с кнопками +1, -1, Сброс
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Компонент ColorPicker — state цвета фона, кнопки переключения темы
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Счётчик кликов в App, передавай count и setCount в дочерний компонент
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Демонстрация функционального апдейта: три setCount(c => c + 1) подряд
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Lazy init: useState(() => JSON.parse(localStorage.getItem('x') ?? '0'))
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Раздели сложный state на несколько useState
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет прямой мутации state (arr.push без копии)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Каждый компонент в отдельном файле

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] DevTools React показывает обновления state

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Создай Vite-проект: npm create vite@latest week-12 -- --template react-ts в learning-log/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Компонент Counter с кнопками +1, -1, Сброс
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Компонент ColorPicker — state цвета фона, кнопки переключения темы
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Счётчик кликов в App, передавай count и setCount в дочерний компонент
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-12\n\ngit add src/components/Counter.tsx src/components/ColorPicker.tsx\n\ngit commit -m "week-12 day-78: useState, Counter и ColorPicker"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Мутация объекта/массива напрямую — UI не обновится

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Вызов setCount(count + 1) три раза подряд в одном обработчике даёт +1, не +3 — используй функциональный апдейт

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 79 (Вт): События и controlled components

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo Pro

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Обработка событий в React похожа на DOM, но есть отличия. Атрибуты пишутся в camelCase: onClick, onChange, onSubmit. React использует Synthetic Events — обёртку над нативными событиями с единым API и пулингом для производительности. e.preventDefault() отменяет действие по умолчанию (перезагрузка формы), e.stopPropagation() останавливает всплытие.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Controlled component — input, значение которого полностью контролируется React state. Для text input: value={text} + onChange={e => setText(e.target.value)}. Для checkbox: checked={done} + onChange, не value. Для select: value={priority} на <select>, не selected на <option>. Группа radio: один state, разные value у <input type=\"radio\">.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Разница readOnly и disabled: disabled элемент не участвует в tab-навигации и не отправляется с формой; readOnly виден и фокусируем, но не редактируется. defaultValue вместо value делает компонент uncontrolled — React не управляет значением после первого рендера. Для форм с валидацией и сбросом предпочитай controlled.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель controlled input — однонаправленный цикл: state → JSX (value) → DOM показывает значение → пользователь печатает → событие onChange → setState → React перерисовывает input с новым value. React в этой схеме — единственный источник правды, а DOM-элемент — лишь его «зеркало». Как только это закольцовано, становится понятно, зачем вообще нужен onChange: не только для валидации, а чтобы замкнуть цикл и не дать полю «зависнуть» со старым значением.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эта модель критична для всего, что будет дальше: формы с валидацией (день 82), поиск с debounce (неделя 13), позже — библиотеки вроде React Hook Form, которые под капотом используют тот же паттерн, просто оптимизированный. Понимание controlled-цикла также объясняет, почему в React сложно «просто взять и вставить jQuery-плагин» — он мутирует DOM в обход React, и React в следующем рендере затирает изменения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: поле поиска <input value={query} onChange={e => setQuery(e.target.value)} /> — при каждом нажатии клавиши React перерисовывает input с тем же символом, который пользователь только что ввёл, поэтому визуально ничего не «дёргается», хотя фактически элемент каждый раз получает новый value из state.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частая ошибка новичков — задать value только при определённом условии (например, value={isEditing ? text : undefined}), из-за чего React в консоли ругается на переключение input между controlled и uncontrolled в процессе жизни компонента. Правило: если хоть раз указал value, указывай его всегда, даже пустой строкой. Именно эта дисциплина понадобится при переписывании Todo App: чекбокс, textarea и select в одной форме должны быть либо все controlled, либо ни один — смешение ведёт к трудноуловимым багам с фокусом и потерянными нажатиями клавиш.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- React — Responding to Events\n- React — Forms\n- react.dev: Controlled vs Uncontrolled

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: controlled input = React state единственный источник правды; value + onChange для каждого поля.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши Todo App (vanilla JS) на React с useState
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Поля: добавление задачи, чекбокс «выполнено», удаление
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Фильтр: All / Active / Completed — отдельный state filter
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Счётчик активных задач в шапке
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Textarea для описания задачи — controlled
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Select приоритета: low / medium / high
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь tab-навигацию по всем полям формы
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Input полностью controlled

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] onSubmit формы с preventDefault

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Фильтрация не мутирует исходный массив

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши Todo App (vanilla JS) на React с useState
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Поля: добавление задачи, чекбокс «выполнено», удаление
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Фильтр: All / Active / Completed — отдельный state filter
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Счётчик активных задач в шапке
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-12\n\ngit add src/components/todo/\n\ngit commit -m "week-12 day-79: controlled inputs и Todo на React"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          defaultValue вместо value — компонент становится uncontrolled

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Забытый key при рендере списка задач — баги при удалении

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 80 (Ср): useEffect — побочные эффекты

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo Pro

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        useEffect синхронизирует React-компонент с внешними системами: DOM API, таймеры, подписки, fetch, localStorage. Сигнатура: useEffect(() => { /* effect */ return () => { /* cleanup */ }; }, [deps]). Пустой массив deps [] — effect выполнится один раз при mount (аналог componentDidMount). [dep] — при изменении dep. Без массива deps — при каждом рендере (почти всегда ошибка).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Cleanup function вызывается перед повторным effect и при unmount: отписка от событий, очистка таймера, abort fetch. Без cleanup — утечки памяти и warnings. React Strict Mode в dev намеренно mount → unmount → mount, чтобы выявить missing cleanup.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не всё требует effect. You Might Not Need an Effect: вычисление derived state, обработка клика, валидация формы — это event handlers, не effects. Effect — для синхронизации с внешним миром, когда нет события-повода. Stale closure — классический баг: effect с [] использует устаревший props/state; добавь их в deps. useLayoutEffect выполняется синхронно после DOM-мутаций, до paint — для измерений layout (обзор).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Полезная мысленная модель, которую подчёркивает сама документация React: useEffect — это не аналог componentDidMount/Update/WillUnmount, а декларативное описание синхронизации. Ты не говоришь React «выполни это после рендера», а говоришь «эта внешняя система должна быть согласована с такими-то значениями»; React сам решает, когда пересинхронизировать — при монтировании, при изменении зависимости, при размонтировании (тогда вызывается cleanup, который «отменяет» предыдущую синхронизацию перед новой).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эта модель станет ключевой на следующий день при работе с fetch (effect синхронизирует UI с состоянием сервера) и через неделю — при написании custom hooks, где вся эта логика инкапсулируется. Она же объясняет глубже, зачем нужен строгий список зависимостей: если effect читает props.city, а зависимостей нет, React не знает, что нужно пересинхронизироваться при смене города — эффект продолжает работать со старым значением из замыкания (тот самый stale closure).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример синхронизации: document.title должен отражать открытую задачу. Effect useEffect(() => { document.title = task.name }, [task.name]) — это не «побочный эффект ради эффекта», а честная синхронизация DOM API (заголовок вкладки) с состоянием React (task.name).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что зависимости управляют «когда запускать effect», как будто это таймер. На самом деле зависимости — это список всех значений извне, которые effect читает; если хоть одно из них не указано, ESLint exhaustive-deps справедливо ругается, потому что effect может работать с устаревшими данными. Ещё одна ошибка — забыть, что cleanup выполняется не только при unmount, но и перед каждым повторным запуском effect, из-за чего Pomodoro-таймер без правильной очистки заводит второй setInterval поверх первого при каждом ререндере, ускоряя обратный отсчёт вместо того, чтобы просто тикать раз в секунду — именно это стоит поймать в практике этого дня на примере таймера и синхронизации localStorage.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- useEffect\n- You Might Not Need an Effect\n- react.dev: Synchronizing with Effects

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: useEffect — для синхронизации с внешним миром; cleanup обязателен; не дублируй логику обработчиков событий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. DocumentTitle — меняет document.title при смене страницы/задачи
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Таймер Pomodoro: 25 мин countdown, cleanup при unmount
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. useEffect с localStorage: загрузка при mount, сохранение при изменении todos
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Нарисуй схему: render → effect → cleanup → re-render
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Подписка на window.resize с cleanup removeEventListener
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Исправь намеренно сломанный effect с missing deps
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Рефакторинг: убери лишний effect, перенеси логику в обработчик
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Таймер очищается при размонтировании

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Зависимости effect указаны корректно (ESLint react-hooks)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет бесконечного цикла effect → setState → effect

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. DocumentTitle — меняет document.title при смене страницы/задачи
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Таймер Pomodoro: 25 мин countdown, cleanup при unmount
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. useEffect с localStorage: загрузка при mount, сохранение при изменении todos
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Нарисуй схему: render → effect → cleanup → re-render
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-12\n\ngit add src/hooks/ src/components/DocumentTitle.tsx\n\ngit commit -m "week-12 day-80: useEffect, Pomodoro и localStorage sync"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Пустой [] при использовании props/state внутри — stale closure

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Effect без deps при каждом рендере — лишние запросы и лаги

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 81 (Чт): Fetch и паттерн loading/error/data

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo Pro

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Загрузка данных в React-компоненте — классический сценарий для useEffect + fetch. Паттерн трёх (или четырёх) состояний: loadingsuccess / error / empty. Реализуй через отдельные useState или discriminated union: { status: 'loading' } | { status: 'error', error: string } | { status: 'success', data: T }. UI рендерит разную разметку в зависимости от status.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        В effect: fetch(url).then(res => { if (!res.ok) throw new Error(); return res.json() }).then(setData).catch(setError).finally(() => setLoading(false)). Fetch не reject на HTTP 404 — проверяй res.ok. Race condition: пользователь быстро переключает id, старый ответ приходит последним. Решение — AbortController в cleanup: const ctrl = new AbortController(); fetch(url, { signal: ctrl.signal }); return () => ctrl.abort().

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не вызывай setState на размонтированном компоненте — abort или флаг let cancelled = false в cleanup. Custom hook useFetch<T>(url) инкапсулирует весь паттерн: loading, error, data, refetch. Skeleton UI вместо пустого экрана улучшает perceived performance.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель здесь — конечный автомат (state machine), а не набор независимых булевых флагов. Если завести отдельные isLoading, isError, data через три useState, ничто не мешает коду случайно оказаться в невозможном состоянии: isLoading = true и isError = true одновременно, хотя по смыслу это взаимоисключающие стадии одного запроса. Discriminated union ({ status: 'idle' | 'loading' | 'success' | 'error', ... }) на уровне типов делает невозможные комбинации невозможными — компилятор TypeScript просто не даст обратиться к data, если status !== 'success'.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это ровно тот паттерн, который будет использоваться весь курс дальше: на неделе 14 при загрузке погоды, на неделях 21–22 при интеграции с собственным backend, и позже как база для понимания библиотек вроде React Query или SWR, которые решают тот же automaton плюс кэширование и повторные запросы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример race condition: пользователь на PostDetail быстро кликает id=1, затем id=2. Запрос за id=1 может по сети завершиться позже, чем запрос за id=2 (например, из-за более тяжёлого ответа), и тогда экран покажет пост id=1, хотя выбран id=2. AbortController в cleanup effect решает это: при смене id предыдущий fetch отменяется до того, как его .then() успеет вызвать setData с устаревшими данными.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать, что достаточно проверить loading, чтобы «на всякий случай» не показывать старые данные; на самом деле без abort или флага cancelled возможен путь, когда компонент уже перешёл к новому запросу, а старый .then() всё равно сработает и молча перезапишет актуальные данные. Именно поэтому в критериях дня явно требуется AbortController в cleanup, а не просто спиннер поверх контента — это прямая защита от этой ошибки при реализации PostList, PostDetail и обобщающего useFetch.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- MDN: Fetch API\n- MDN: AbortController\n- JSONPlaceholder

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: fetch в effect требует loading/error states, проверки res.ok, abort в cleanup и защиты от race condition.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Компонент PostList — GET /posts, спиннер при загрузке
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Обработка ошибки сети — блок с кнопкой «Повторить»
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. PostDetail — загрузка /posts/:id по клику
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Skeleton-заглушки вместо пустого экрана
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. AbortController в cleanup при смене id или unmount
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Вынеси логику в useFetch<T>(url)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Empty state: «Постов не найдено» при пустом массиве
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] AbortController в cleanup effect

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] UI для loading, error, empty, success

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет setState на размонтированном компоненте

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Компонент PostList — GET /posts, спиннер при загрузке
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Обработка ошибки сети — блок с кнопкой «Повторить»
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. PostDetail — загрузка /posts/:id по клику
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Skeleton-заглушки вместо пустого экрана
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-12\n\ngit add src/hooks/useFetch.ts src/components/PostList.tsx\n\ngit commit -m "week-12 day-81: fetch, loading/error/data и useFetch"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Забытый cleanup → warning «Can't perform state update on unmounted component»

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Race condition: старый запрос перезаписывает новый — используй abort или id запроса

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 82 (Пт): Формы в React

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo Pro

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Формы в React строятся на controlled components: каждое поле связано с state. Для формы из нескольких полей два подхода: отдельный useState на поле (проще для маленьких форм) или один объект const [form, setForm] = useState({ name: '', email: '' }) с обновлением setForm(f => ({ ...f, name: e.target.value })). Второй удобен для submit целиком и сброса.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Валидация на клиенте: required, minLength, regex для email, кастомные правила (пароль ≥ 8 символов). UX-паттерн touched/dirty: показывай ошибки после blur или submit, не при первом символе — это меньше раздражает. useId() генерирует стабильный уникальный id для связки <label htmlFor={id}> и <input id={id}> — важно для accessibility.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Сброс формы: верни state к начальным значениям. noValidate на <form> отключает браузерную валидацию, если реализуешь свою. Checkbox «согласен с условиями» — отдельный boolean state, блокирующий submit. React 19 Form Actions (обзор) упрощают submit через action prop, но controlled подход остаётся фундаментом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель формы: единый объект состояния полей (form) плюс отдельный, вычисляемый на каждый рендер объект ошибок (errors), а не два независимых, синхронизируемых вручную state. Ошибки — производная функция от form и правил валидации: validate(form) вызывается при рендере или в обработчике submit/blur, а не хранится как отдельный useState, который легко забыть обновить и получить рассинхрон между полем и текстом ошибки под ним.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это станет фундаментом для форм логина на день 89 этой же недели (React Router + Context), а позже — для форм, отправляющих данные на собственный backend (недели 21+), где к клиентской валидации добавится обработка ошибок сервера (409 Conflict на занятый email и подобное) поверх той же структуры state.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: поле «Подтвердите пароль» валидируется не изолированно, а в сравнении с полем «Пароль» — errors.confirmPassword = form.password !== form.confirmPassword ? 'Пароли не совпадают' : null. Это наглядно показывает, что ошибка — производная от всей формы, а не свойство одного поля.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — показывать ошибку сразу при первом введённом символе: пользователь ещё не закончил печатать email, а поле уже красное. UX-паттерн touched/dirty (ошибка показывается после blur или после первой попытки submit) снижает раздражение, но требует дисциплины: touched — тоже часть state формы, обновляемая в onBlur. Другая типичная ошибка — хранить isFormValid отдельным state вместо вычисления Object.keys(errors).length === 0 при каждом рендере; при отдельном state легко забыть его обновить после изменения одного из полей, и кнопка submit останется disabled даже у корректно заполненной формы. Именно такую логику нужно продумать при реализации формы регистрации: имя, email, пароль с подтверждением и чекбокс согласия должны валидироваться согласованно, без рассинхрона между полем, ошибкой и состоянием кнопки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- React — Forms\n- React — input\n- useId

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: форма = набор controlled fields + валидация + сброс state; ошибки показывай после blur/submit, не мгновенно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Форма регистрации: имя, email, пароль, роль (select)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Валидация перед submit: email формат, пароль ≥ 8 символов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Ошибки под полями, disabled кнопка при невалидной форме
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. После успешного submit — очистка формы и toast-сообщение
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Checkbox «согласен с условиями» — обязательный для submit
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Показ/скрытие пароля кнопкой-иконкой
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. useId() для всех label/input пар
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Все поля controlled

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Ошибки показываются только после blur или submit

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] type=\"password\" и autoComplete настроены

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Форма регистрации: имя, email, пароль, роль (select)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Валидация перед submit: email формат, пароль ≥ 8 символов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Ошибки под полями, disabled кнопка при невалидной форме
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. После успешного submit — очистка формы и toast-сообщение
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-12\n\ngit add src/components/RegisterForm.tsx\n\ngit commit -m "week-12 day-82: форма регистрации и валидация"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          onChange на checkbox без checked={} — неконтролируемый чекбокс

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Валидация только на submit без UX-подсказок — плохой UX

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 83 (Сб): Подъём state (lifting state up)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo Pro

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Lifting state up (подъём состояния) решает задачу, когда два или более компонента должны отображать или изменять одни данные. State перемещается к ближайшему общему родителю. Родитель хранит данные и передаёт вниз через props; дети сообщают об изменениях через callback props (onSearchChange, onSortChange). Siblings никогда не общаются напрямую — только через родителя.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Derived state — значения, вычисляемые из props или state при рендере: const filtered = items.filter(i => i.title.includes(query)). Не дублируй их в отдельном useState — иначе рассинхрон при обновлении источника. Prop drilling на 1–2 уровня — нормально; при глубокой вложенности (неделя 13) поможет Context.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Container/Presentational split: «умный» компонент управляет state и логикой, «глупый» — только рендерит по props. useMemo (preview) кэширует результат дорогой фильтрации: useMemo(() => items.filter(...), [items, query]) — пересчёт только при изменении deps. Для 10 элементов не нужен; для 1000+ — заметная оптимизация.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель для lifting state up формулируется просто: «state должен жить настолько низко, насколько возможно, и настолько высоко, насколько необходимо». Это значит — не поднимай вообще всё в корень приложения «на всякий случай»: если состояние нужно только одному компоненту (например, открыт ли dropdown), оно остаётся локальным; поднимается только то, что реально требуется нескольким потребителям одновременно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Этот баланс станет критичным на следующей неделе, когда drilling через 4–5 уровней станет неудобным и появится соблазн засунуть вообще всё в Context. Понимание сегодняшнего правила помогает не наступить на грабли «Context для всего»: то, что нужно двум соседним компонентам на одном уровне, поднимается к родителю (как сегодня), а Context нужен только для данных, нужных по-настоящему широко и на разной глубине дерева (тема, авторизация).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: SearchBar не может держать searchQuery у себя, а ItemList — фильтровать по нему, если они не знают друг о друге. Оба — дети одного родителя FilterableList, значит, searchQuery поднимается именно туда: родитель хранит state, передаёт value и onChange в SearchBar, а отфильтрованный список — в ItemList.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частая ошибка — воспринять «lifting state up» как сигнал переносить в родителя вообще все данные компонента, включая чисто визуальные вещи вроде «наведена ли мышь на элемент» или «раскрыт ли аккордеон» — это только раздувает родителя и провоцирует лишние ререндеры всего поддерева при каждом мелком UI-взаимодействии. Правило простое: поднимай ровно то состояние, которое читают или меняют минимум два разных компонента; всё остальное остаётся локальным. Именно на этом принципе строится рефакторинг Todo App в практике дня: filter и searchQuery поднимаются в общий родитель, а, например, состояние «редактируется ли конкретная задача прямо сейчас» может вполне остаться внутри TodoItem.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- Sharing State Between Components\n- react.dev: Extracting State Logic into a Reducer — preview\n- useMemo

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: общий state — у ближайшего родителя; derived values вычисляй, не дублируй в useState.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. FilterableList: родитель хранит items + searchQuery
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. SearchBar — только input, вызывает onSearchChange
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. ItemList — получает отфильтрованный массив, рендерит список
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. ItemCount — показывает «Найдено: N из M»
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Добавь сортировку (A–Z / Z–A) — ещё один поднятый state
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Вынеси фильтрацию в useMemo при 100+ элементах (mock)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Рефакторинг Todo: filter + search в одном родителе
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] SearchBar не знает про items — только про query

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Фильтрация в родителе или через useMemo

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет дублирования state в siblings

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. FilterableList: родитель хранит items + searchQuery
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. SearchBar — только input, вызывает onSearchChange
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. ItemList — получает отфильтрованный массив, рендерит список
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. ItemCount — показывает «Найдено: N из M»
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-12\n\ngit add src/components/FilterableList/\n\ngit commit -m "week-12 day-83: lifting state, FilterableList и сортировка"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Дублирование одного state в двух дочерних компонентах — рассинхрон

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Слишком глубокий drilling — пока терпимо, Context на неделе 13

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 84 (Вс): Ревью и углубление

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Todo Pro

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью недели — время закрепить правила hooks и подготовиться к React Todo Pro. Правила hooks: вызывай только на верхнем уровне (не в if/for) и только в React-функциях (компонентах или custom hooks). Нарушение ломает порядок hooks между рендерами. Custom hook — функция useTodos(), внутри которой useState + handlers; компонент остаётся тонким, логика переиспользуема.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        React DevTools показывают дерево компонентов, props и state в реальном времени — незаменимый инструмент отладки. ESLint react-hooks/exhaustive-deps предупреждает о missing dependencies в useEffect — не отключай правило без веской причины и комментария. Strict Mode двойной mount — норма в dev, не баг.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Чеклист code review: state обновляется иммутабельно, effects имеют cleanup, inputs controlled, deps корректны, нет setState на unmounted компоненте. Конспект «useState vs useEffect»: state — для данных UI, effect — для синхронизации с внешним миром. Подготовка к Todo Pro: приоритеты, дедлайны, Quotable API — всё на базе изученных паттернов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель, объясняющая Rules of Hooks: React хранит хуки одного компонента как позиционный список — при каждом рендере он ожидает вызовы useState, useEffect и других хуков строго в одном и том же порядке, чтобы сопоставить i-й вызов с i-й ячейкой памяти. Хук не «знает» своё имя переменной, только позицию вызова. Если между рендерами хук иногда вызывается, а иногда пропускается (например, из-за if перед useState), позиции всех последующих хуков смещаются, и React начинает путать состояние одного хука с другим.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это понимание становится обязательным на следующей неделе при написании собственных custom hooks: любая условная логика внутри useLocalStorage или useFetch должна быть внутри хука, а не вокруг вызова самого хука. Ошибка на этом уровне не бросает явное исключение сразу — она проявляется как труднообъяснимый баг «состояние перепуталось» через несколько рендеров, что делает её особенно коварной в более крупных проектах.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример нарушения: if (user) { const [notifications] = useState([]); } — если user появляется не сразу, а после начального рендера, хук, который раньше был третьим по счёту, эту логику меняет, и React ломает сопоставление предыдущих состояний с новыми вызовами.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — воспринимать хуки как «обычные функции», которые можно оборачивать в любые конструкции языка, как обычный useCallback-помощник. На самом деле особый рантайм React делает их зависимыми от порядка вызова, а не от имени — отсюда и линтер react-hooks/rules-of-hooks, который стоит воспринимать не как формальность, а как страховку от невидимых багов. В практике дня это напрямую связано с вынесением логики Todo в useTodos: рефакторинг должен сохранить безусловный порядок вызовов хуков, а Tic-Tac-Toe из официального туториала — хорошая тренировка на управление историей состояния через массив снимков, ту же модель, что используется в Undo/Redo многих реальных приложений.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:\n- React DevTools\n- Rules of Hooks\n- React Strict Mode

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ключевая мысль: custom hooks выносят логику из компонентов; правила hooks и exhaustive-deps — страховка от типичных багов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди React Tutorial — Tic-Tac-Toe до конца
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рефакторинг Todo App: вынеси логику в useTodos (заготовка под custom hook)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Code review своего кода: immutability, deps, cleanup
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Начни скелет React Todo Pro — типы с priority и deadline
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Конспект «useState vs useEffect — когда что» на 1 страницу
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Прогони ESLint без warnings
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-12-done после финальной сборки
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Tic-Tac-Toe работает с историей ходов

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] ESLint react-hooks/exhaustive-deps без warnings

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Конспект «useState vs useEffect — когда что» на 1 страницу

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди React Tutorial — Tic-Tac-Toe до конца
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рефакторинг Todo App: вынеси логику в useTodos (заготовка под custom hook)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Code review своего кода: immutability, deps, cleanup
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Начни скелет React Todo Pro — типы с priority и deadline
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-12\n\ngit add .\n\ngit commit -m "week-12 day-84: useTodos, Tic-Tac-Toe и React Todo Pro скелет"\n\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        React Todo Pro — полнофункциональное приложение задач. Подробное ТЗ: docs/projects.md — Неделя 12.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. \n

                                                                                                                                                                                                                          CRUD задач с приоритетом (low/medium/high) и дедлайном

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. \n

                                                                                                                                                                                                                          Фильтры: статус, приоритет, поиск по тексту

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. \n

                                                                                                                                                                                                                          Persist в localStorage через useEffect

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. \n

                                                                                                                                                                                                                          Загрузка «мотивационной цитаты» с Quotable API

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. \n

                                                                                                                                                                                                                          Адаптивная вёрстка, тёмная тема через CSS-переменные

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] useState + useEffect без антипаттернов

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Controlled форма добавления задачи

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Lifting state: фильтры и список согласованы

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Quotable API с loading/error states

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Custom hook useTodos для логики CRUD

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] README с инструкцией запуска

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тег week-12-done

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Могу объяснить, почему setState асинхронный и что такое batching?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Чем controlled отличается от uncontrolled input?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Зачем cleanup в useEffect? Приведи 2 примера.

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Когда поднимать state, а когда оставить локальным?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Что произойдёт, если мутировать массив в state напрямую?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **React Todo Pro** в `learning-log/week-12/`, осмысленная Git-история, тег `week-12-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nReact hooks, effects, формы\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-12-day-78", "label": "День 78 (Пн): useState — память компонента"}, {"id": "week-12-day-79", "label": "День 79 (Вт): События и controlled components"}, {"id": "week-12-day-80", "label": "День 80 (Ср): useEffect — побочные эффекты"}, {"id": "week-12-day-81", "label": "День 81 (Чт): Fetch и паттерн loading/error/data"}, {"id": "week-12-day-82", "label": "День 82 (Пт): Формы в React"}, {"id": "week-12-day-83", "label": "День 83 (Сб): Подъём state (lifting state up)"}, {"id": "week-12-day-84", "label": "День 84 (Вс): Ревью и углубление"}, {"id": "week-12-project", "label": "Проект недели"}, {"id": "week-12-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-12-review", "label": "Проверь себя"}], "text": "Неделя 12: React — state, эффекты, формы Цель недели: научиться управлять состоянием компонентов, побочными эффектами и формами в React. Литература: react.dev — Learn , React — State , React — Effects , You Might Not Need an Effect , React — Forms Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-12/ День 78 (Пн): useState — память компонента Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к React Todo Pro Теория useState — фундаментальный hook React, дающий функциональному компоненту локальное состояние. При первом рендере React создаёт ячейку state; при последующих — возвращает сохранённое значение. setState не меняет переменную мгновенно…"} \ No newline at end of file diff --git a/docs/weeks/13.json b/docs/weeks/13.json index 9e26080..4d12344 100644 --- a/docs/weeks/13.json +++ b/docs/weeks/13.json @@ -1 +1 @@ -{"id": "week-13", "title": "Router & Context", "fullTitle": "Неделя 13: React Router, хуки, Context", "html": "

                                                                                                                                                                                                                        Неделя 13: React Router, хуки, Context

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: построить многостраничное SPA с переиспользуемой логикой и глобальным состоянием.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература: React Router, react.dev — Context, react.dev — Reusing Logic, React Router Tutorial, useDebounce patterns

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git: минимум 1 осмысленный коммит каждый день в learning-log/week-13/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 85 (Пн): React Router — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio SPA

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Одностраничное приложение (SPA) живёт в одной HTML-странице, но пользователь ожидает поведение «настоящего сайта»: разные URL, кнопка «Назад» в браузере, закладки на конкретные экраны. React Router решает эту задачу на клиенте: при смене маршрута он размонтирует один набор компонентов и смонтирует другой, не перезагружая документ целиком.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Три кита базовой настройки — BrowserRouter, Routes и Route. Router подключает приложение к History API браузера (pushState под капотом); Routes выбирает единственный подходящий маршрут; Route связывает путь с компонентом. Для навигации внутри SPA используй Link или NavLink: они меняют URL без полной перезагрузки, в отличие от обычного <a href>, который сбрасывает состояние приложения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Layout с <Outlet /> — стандартный паттерн общей оболочки: шапка и меню остаются на месте, а содержимое страницы подставляется в outlet. Catch-all маршрут path=\"*\" обязателен для 404. При деплое в subdirectory (GitHub Pages) понадобится basename; сервер должен отдавать index.html на все пути, иначе прямой заход по URL /about вернёт 404 от nginx, а не твой React-компонент.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: SPA-навигация — смена компонентов без перезагрузки; для внутренних ссылок — Link, не <a>.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install react-router-dom в learning-log/week-13/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Страницы: / Home, /about About, /contact Contact
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Layout с <Outlet /> — общая шапка и навигация
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. NavLink с активным классом для текущей страницы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Страница 404 с ссылкой на главную
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Вынеси маршруты в src/routes.tsx или App.tsx
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь: прямой переход по URL /about работает (dev server)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Навигация без полной перезагрузки страницы

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] 404-страница path=\"*\"

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Layout оборачивает все маршруты

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install react-router-dom в learning-log/week-13/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Страницы: / Home, /about About, /contact Contact
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Layout с <Outlet /> — общая шапка и навигация
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. NavLink с активным классом для текущей страницы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-13\n\ngit add src/pages/ src/components/Layout.tsx\n\ngit commit -m "week-13 day-85: React Router, Layout и 404"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          BrowserRouter внутри BrowserRouter — ошибка вложенности

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          <a href> вместо <Link> — полная перезагрузка, теряется SPA

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 86 (Вт): Динамические маршруты и nested routes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio SPA

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Статический маршрут /about покрывает фиксированную страницу, но реальные приложения оперируют сущностями с идентификаторами: посты, проекты, профили. Динамический сегмент /blog/:slug превращает часть URL в параметр, который компонент читает через useParams. Помни: все параметры приходят строками — для чисел нужны Number() или явная валидация.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Вложенные маршруты (nested routes) строят иерархию UI: общий layout для раздела /blog и дочерние страницы списка и детали. Родительский Route рендерит layout с <Outlet />; без outlet дочерние страницы просто не появятся — классическая ловушка. Index route задаёт страницу по умолчанию, когда пользователь открывает родительский путь без суффикса.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Query string (?sort=date&tab=comments) описывает фильтры и вкладки, не меняя структуру пути. useSearchParams даёт к ним доступ в React-стиле. useLocation полезен для breadcrumbs и для передачи временного state при navigate('/path', { state: { from: 'list' } }). В React Router 6.4+ useMatches помогает строить цепочку навигации из дерева маршрутов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: путь описывает «где», query — «как показать»; параметры маршрута всегда строки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. /blog — список постов, /blog/:slug — детальная страница
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Данные постов — mock JSON или JSONPlaceholder
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Breadcrumbs: Home → Blog → Post Title
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Query ?sort=date — сортировка списка
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Несуществующий slug → страница «Не найдено»
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Nested layout для /blog с sidebar категорий
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. useSearchParams для tab: ?tab=comments
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] useParams корректно читает :slug

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Несуществующий slug → страница «Не найдено»

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Breadcrumbs обновляются при навигации

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. /blog — список постов, /blog/:slug — детальная страница
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Данные постов — mock JSON или JSONPlaceholder
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Breadcrumbs: Home → Blog → Post Title
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Query ?sort=date — сортировка списка
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-13\n\ngit add src/pages/blog/\n\ngit commit -m "week-13 day-86: динамические маршруты и breadcrumbs"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Параметр :id всегда string — нужен Number(id) или валидация

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Забытый <Outlet /> в layout — дочерние страницы не рендерятся

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 87 (Ср): Custom Hooks — переиспользование логики

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio SPA

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Custom hook — обычная функция с префиксом use, внутри которой вызываются другие хуки. Она не добавляет новых возможностей React, а выносит повторяющуюся логику из компонентов: синхронизацию с localStorage, загрузку данных, debounce ввода. Компонент остаётся про UI, хук — про поведение.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Типичный useLocalStorage(key, initial) комбинирует useState и useEffect: при изменении state значение пишется в storage, при монтировании — читается обратно. Оборачивай JSON.parse в try/catch — битые данные не должны ронять приложение. useFetch(url) инкапсулирует три состояния (loading, error, data) и избавляет каждую страницу от копипасты useEffect.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        useDebounce(value, delay) откладывает обновление: пока пользователь печатает в поиске, тяжёлая фильтрация не запускается на каждый символ. Правила хуков действуют и внутри custom hook — нельзя вызывать хуки условно. Возвращай объект { data, loading } или tuple, но придерживайся одного стиля в проекте.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: custom hook извлекает логику, а не UI; правила хуков обязательны внутри него.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реализуй useLocalStorage с JSON parse/stringify
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. useFetch(url) — возвращает { data, loading, error, refetch }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. useDebounce(value, 300) — для поля поиска в FilterableList
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Покрой хуки простыми тестами вручную (console + checklist)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. useMediaQuery('(min-width: 768px)') — responsive hook
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Вынеси хуки в src/hooks/ с index re-export
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. JSDoc/TSDoc для публичного API каждого хука
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Хуки в папке src/hooks/

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] useLocalStorage работает после F5

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] useDebounce уменьшает количество фильтраций

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реализуй useLocalStorage с JSON parse/stringify
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. useFetch(url) — возвращает { data, loading, error, refetch }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. useDebounce(value, 300) — для поля поиска в FilterableList
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Покрой хуки простыми тестами вручную (console + checklist)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-13\n\ngit add src/hooks/\n\ngit commit -m "week-13 day-87: useLocalStorage, useFetch и useDebounce"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Условный вызов хуков внутри custom hook — нарушение Rules of Hooks

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          useLocalStorage без try/catch при битом JSON в storage

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 88 (Чт): Context API — глобальное состояние

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio SPA

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Prop drilling — передача props через пять уровней дерева — быстро превращает код в лабиринт. Context API даёт альтернативу: Provider в корне публикует значение, любой потомок читает его через useContext без промежуточных компонентов. Классические кандидаты: тема оформления, язык интерфейса, данные текущего пользователя.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        createContext(defaultValue) создаёт контекст; default нужен для подсказок в dev и как fallback, если забыли Provider. Разделяй контексты по доменам: ThemeContext отдельно от UserContext, иначе смена темы перерисует всё дерево, включая компоненты, которым нужен только user. Оборачивай value Provider в useMemo, если передаёшь объект или функции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Context не заменяет локальный state и не является полноценным store. Документация React предупреждает: не тащи в Context часто меняющиеся данные. Для сложного глобального state комбинация Context + useReducer — разумный следующий шаг, но для учебного проекта двух отдельных контекстов (theme + user) достаточно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: Context — для редко меняющихся глобальных данных; разделяй провайдеры и мемоизируй value.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. ThemeContext: theme, toggleTheme, CSS-класс dark на <html>
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. UserContext: имя пользователя, setName — форма в Settings
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Потребители на разных страницах без prop drilling
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Вынеси Provider в App.tsx один раз
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Persist theme в localStorage через useEffect в Provider
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Custom hook useTheme() — обёртка над useContext
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь: смена темы на /settings отражается на /
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тема сохраняется в localStorage

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Минимум 3 компонента используют Context без промежуточных props

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Default value в createContext для dev-подсказок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. ThemeContext: theme, toggleTheme, CSS-класс dark на <html>
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. UserContext: имя пользователя, setName — форма в Settings
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Потребители на разных страницах без prop drilling
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Вынеси Provider в App.tsx один раз
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-13\n\ngit add src/contexts/\n\ngit commit -m "week-13 day-88: ThemeContext и UserContext"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Один Context на всё приложение — лишние ререндеры при любом изменении

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Забытый Provider — useContext возвращает default, баги «молча»

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 89 (Пт): Комбинация Router + Context + Hooks

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio SPA

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        На этой неделе складываются три слоя: Router отвечает за URL, Context — за глобальное состояние (auth, theme), custom hooks — за переиспользуемую логику. Protected route — тонкая обёртка: если в AuthContext нет пользователя, рендерится <Navigate to=\"/login\" replace />, иначе — дочерняя страница.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Mock-авторизация без реального API — нормальная ступень обучения: сохраняй объект user в localStorage, восстанавливай при старте. Без persist пользователь «разлогинится» после F5. Logout должен атомарно очистить Context, storage и перенаправить на публичную страницу через useNavigate или декларативный <Navigate>.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Разделяй ответственность: форма логина — controlled inputs; проверка доступа — в ProtectedRoute; данные сессии — в Context. location.state позволяет передать, откуда пришёл пользователь, чтобы после login вернуть его на исходную страницу, а не всегда на /dashboard.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: protected route проверяет сессию на уровне маршрута; persist в storage переживает перезагрузку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. AuthContext с user, login, logout (mock, без реального API)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. ProtectedRoute — children или <Navigate to=\"/login\" />
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. /dashboard — только для авторизованных
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. После login — navigate('/dashboard', { replace: true })
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Страница /login — controlled form, mock credentials
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Persist user в localStorage — переживает F5
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Header: кнопка Logout на всех страницах
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Неавторизованный пользователь не видит /dashboard

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Logout очищает Context и редиректит на /

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Login form — controlled inputs

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. AuthContext с user, login, logout (mock, без реального API)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. ProtectedRoute — children или <Navigate to=\"/login\" />
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. /dashboard — только для авторизованных
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. После login — navigate('/dashboard', { replace: true })
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-13\n\ngit add src/contexts/AuthContext.tsx src/components/ProtectedRoute.tsx\n\ngit commit -m "week-13 day-89: AuthContext и protected routes"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Хранение «авторизации» только в state без persist — F5 разлогинивает

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Protected route проверяет только наличие объекта, не валидность token (позже на нед. 20)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 90 (Сб): Оптимизация и структура проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio SPA

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        К концу недели проект обрастает папками: pages/, components/, hooks/, contexts/, utils/. Предсказуемая структура важнее идеальной: новый разработчик (или ты через месяц) должен за минуту найти, где живут маршруты и где — хуки. ARCHITECTURE.md фиксирует решения, а не дублирует README с командами запуска.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Оптимизация в React начинается с измерения, а не с useMemo на каждой функции. Profiler в DevTools показывает лишние ререндеры. React.lazy + Suspense разбивают bundle: тяжёлая страница /admin загружается только при переходе. useMemo оправдан для дорогих вычислений; useCallback — когда передаёшь колбэк в React.memo-компонент.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Barrel exports (index.ts) ускоряют импорты, но могут ухудшить tree-shaking — используй осознанно. useCallback без memoized child бесполезен. Преждевременная мемоизация усложняет код без выигрыша: сначала работающее приложение, потом профилирование, потом точечные правки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: оптимизируй после профилирования; lazy routes уменьшают начальный bundle.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реорганизуй проект недели по папкам
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Lazy-load страницу /admin с fallback-спиннером
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. useMemo для дорогой фильтрации списка (1000+ элементов — mock)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Документируй архитектуру в ARCHITECTURE.md (1 страница)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. React.memo на TodoItem — измерь, есть ли выгода
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Suspense boundary с понятным fallback UI
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь bundle size после lazy loading
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Импорты страниц через React.lazy

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет useMemo/useCallback «на всякий случай» без причины

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Понятная структура папок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реорганизуй проект недели по папкам
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Lazy-load страницу /admin с fallback-спиннером
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. useMemo для дорогой фильтрации списка (1000+ элементов — mock)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Документируй архитектуру в ARCHITECTURE.md (1 страница)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-13\n\ngit add ARCHITECTURE.md src/pages/\n\ngit commit -m "week-13 day-90: lazy routes, useMemo и структура"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Преждевременная оптимизация — сначала работающий код, потом профилирование

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          useCallback без memoized child — бесполезен

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 91 (Вс): Ревью паттернов React

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio SPA

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        За семь дней ты собрал многостраничное SPA с роутингом, глобальным state и переиспользуемыми хуками. Полезно явно сравнить инструменты: локальный state для UI формы, lifting state когда нужно двум соседям, custom hook для логики, Context для редких глобальных данных, внешний store (Zustand/Redux) — когда Context разрастается.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Error Boundary ловит ошибки рендеринга в дочерних компонентах и показывает fallback вместо белого экрана. Оберни <Routes> или отдельные страницы, чтобы сбой на /blog/:slug не убивал всё приложение. Boundary не ловит ошибки в event handlers и async-коде — только синхронный render.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Перед деплоем проверь client-side routing: хостинг должен отдавать index.html на все пути. Portfolio SPA — витрина навыков недели: осмысленные коммиты за 7 дней, preview URL, README с картой маршрутов. Скелет Dashboard на неделю 14 логично начать с тех же паттернов Layout + Context + hooks.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: выбор инструмента state — по частоте изменений и глубине дерева, не «всё в Context».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Добавь простой Error Boundary вокруг <Routes>
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Пройди чеклист своего многостраничного приложения
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Запиши ответы: «Когда Context, когда custom hook, когда lifting state?»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Подготовь skeleton для Dashboard (неделя 14)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Финализируй Portfolio SPA — все маршруты и hooks
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Deploy preview на Vercel/Netlify
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-13-done
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Error Boundary ловит ошибку в дочернем компоненте

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Написан план страниц Dashboard: /, /tasks, /weather, /settings

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Git commit за каждый день недели

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Добавь простой Error Boundary вокруг <Routes>
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Пройди чеклист своего многостраничного приложения
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Запиши ответы: «Когда Context, когда custom hook, когда lifting state?»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Подготовь skeleton для Dashboard (неделя 14)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-13\n\ngit add .\n\ngit commit -m "week-13 day-91: Error Boundary и Portfolio SPA deploy"\n\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Personal Portfolio SPA (промежуточный, перед Dashboard). Подробное ТЗ: docs/projects.md — Неделя 13.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. \n

                                                                                                                                                                                                                          Роутинг: Home, Projects, Project Detail :id, Blog, Contact

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. \n

                                                                                                                                                                                                                          ThemeContext + useLocalStorage

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. \n

                                                                                                                                                                                                                          Custom hooks: useFetch для GitHub API (repos), useDebounce для поиска проектов

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. \n

                                                                                                                                                                                                                          Protected /admin с mock-auth

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. \n

                                                                                                                                                                                                                          Адаптивная навигация (бургер-меню на мобиле)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] ≥ 5 маршрутов, nested layout

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] ≥ 2 custom hooks, ≥ 1 Context

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] 404, loading states, error handling

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] GitHub API repos на странице Projects

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Деплой на GitHub Pages или Vercel (preview)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] README с URL и описанием маршрутов

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тег week-13-done

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Чем Link отличается от обычной <a>?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Как передать query-параметры и прочитать их?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Зачем custom hook, если можно просто функцию?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Когда Context вызывает лишние ререндеры?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Как защитить маршрут от неавторизованного доступа?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Portfolio SPA** в `learning-log/week-13/`, осмысленная Git-история, тег `week-13-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nReact Router, Context, custom hooks\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-13-day-85", "label": "День 85 (Пн): React Router — основы"}, {"id": "week-13-day-86", "label": "День 86 (Вт): Динамические маршруты и nested routes"}, {"id": "week-13-day-87", "label": "День 87 (Ср): Custom Hooks — переиспользование логики"}, {"id": "week-13-day-88", "label": "День 88 (Чт): Context API — глобальное состояние"}, {"id": "week-13-day-89", "label": "День 89 (Пт): Комбинация Router + Context + Hooks"}, {"id": "week-13-day-90", "label": "День 90 (Сб): Оптимизация и структура проекта"}, {"id": "week-13-day-91", "label": "День 91 (Вс): Ревью паттернов React"}, {"id": "week-13-project", "label": "Проект недели"}, {"id": "week-13-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-13-review", "label": "Проверь себя"}], "text": "Неделя 13: React Router, хуки, Context Цель недели: построить многостраничное SPA с переиспользуемой логикой и глобальным состоянием. Литература: React Router , react.dev — Context , react.dev — Reusing Logic , React Router Tutorial , useDebounce patterns Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-13/ День 85 (Пн): React Router — основы Время (полный): ~1.5ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Portfolio SPA Теория Одностраничное приложение (SPA) живёт в одной HTML-странице, но пользователь ожидает поведение «настоящего сайта»: разные URL, кнопка «Назад» в браузере, закладки на конкретные экраны. React Router решает эту задачу на клиенте: п…"} \ No newline at end of file +{"id": "week-13", "title": "Router & Context", "fullTitle": "Неделя 13: React Router, хуки, Context", "html": "

                                                                                                                                                                                                                        Неделя 13: React Router, хуки, Context

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: построить многостраничное SPA с переиспользуемой логикой и глобальным состоянием.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература: React Router, react.dev — Context, react.dev — Reusing Logic, React Router Tutorial, useDebounce patterns

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git: минимум 1 осмысленный коммит каждый день в learning-log/week-13/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 85 (Пн): React Router — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio SPA

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Одностраничное приложение (SPA) живёт в одной HTML-странице, но пользователь ожидает поведение «настоящего сайта»: разные URL, кнопка «Назад» в браузере, закладки на конкретные экраны. React Router решает эту задачу на клиенте: при смене маршрута он размонтирует один набор компонентов и смонтирует другой, не перезагружая документ целиком.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Три кита базовой настройки — BrowserRouter, Routes и Route. Router подключает приложение к History API браузера (pushState под капотом); Routes выбирает единственный подходящий маршрут; Route связывает путь с компонентом. Для навигации внутри SPA используй Link или NavLink: они меняют URL без полной перезагрузки, в отличие от обычного <a href>, который сбрасывает состояние приложения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Layout с <Outlet /> — стандартный паттерн общей оболочки: шапка и меню остаются на месте, а содержимое страницы подставляется в outlet. Catch-all маршрут path=\"*\" обязателен для 404. При деплое в subdirectory (GitHub Pages) понадобится basename; сервер должен отдавать index.html на все пути, иначе прямой заход по URL /about вернёт 404 от nginx, а не твой React-компонент.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель React Router: URL — это ещё один источник состояния приложения, только он живёт не в React, а в браузере (History API), и Router — это просто мост, который синхронизирует адресную строку с деревом React-компонентов. Смена маршрута — это не HTTP-запрос за новой страницей, а вызов pushState, который меняет URL без перезагрузки, после чего Routes перечитывает текущий путь и решает, какое поддерево компонентов сейчас должно быть смонтировано.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эта модель — фундамент всего, что будет дальше на неделе: вложенные маршруты (день 86) — это просто вложенные решения «какое поддерево показать»; protected routes (день 89) — это условный рендер <Navigate> вместо целевого компонента; а на деплое (день 91) станет ясно, что клиентский роутинг работает только пока JS-бандл загружен в браузере — прямой заход по URL требует отдельной настройки сервера.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример путаницы клиент/сервер: пользователь кликает NavLink на /about — React Router перехватывает клик, меняет URL через pushState и рендерит About без единого сетевого запроса. Но если тот же пользователь наберёт /about в адресной строке и нажмёт Enter, браузер отправит настоящий HTTP-запрос на сервер, и если сервер (nginx, statically-hosted файлы) не настроен отдавать index.html на любой путь, он ответит честным 404 Not Found — не потому что React сломался, а потому что запрос вообще не дошёл до React.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение новичков — думать, что React Router «делает запросы» за страницы, как многостраничный сайт, и что 404 при обновлении страницы — это баг библиотеки, а не следствие неправильной настройки сервера или отсутствия basename при деплое в поддиректорию. Именно поэтому в практике дня явно указан пункт «прямой переход по URL /about работает» — это проверка не только кода, но и понимания разницы между dev server (который из коробки настроен на SPA fallback) и продакшен-хостингом, который нужно настраивать отдельно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: SPA-навигация — смена компонентов без перезагрузки; для внутренних ссылок — Link, не <a>.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install react-router-dom в learning-log/week-13/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Страницы: / Home, /about About, /contact Contact
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Layout с <Outlet /> — общая шапка и навигация
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. NavLink с активным классом для текущей страницы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Страница 404 с ссылкой на главную
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Вынеси маршруты в src/routes.tsx или App.tsx
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь: прямой переход по URL /about работает (dev server)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Навигация без полной перезагрузки страницы

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] 404-страница path=\"*\"

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Layout оборачивает все маршруты

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install react-router-dom в learning-log/week-13/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Страницы: / Home, /about About, /contact Contact
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Layout с <Outlet /> — общая шапка и навигация
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. NavLink с активным классом для текущей страницы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-13\n\ngit add src/pages/ src/components/Layout.tsx\n\ngit commit -m "week-13 day-85: React Router, Layout и 404"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          BrowserRouter внутри BrowserRouter — ошибка вложенности

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          <a href> вместо <Link> — полная перезагрузка, теряется SPA

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 86 (Вт): Динамические маршруты и nested routes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio SPA

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Статический маршрут /about покрывает фиксированную страницу, но реальные приложения оперируют сущностями с идентификаторами: посты, проекты, профили. Динамический сегмент /blog/:slug превращает часть URL в параметр, который компонент читает через useParams. Помни: все параметры приходят строками — для чисел нужны Number() или явная валидация.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Вложенные маршруты (nested routes) строят иерархию UI: общий layout для раздела /blog и дочерние страницы списка и детали. Родительский Route рендерит layout с <Outlet />; без outlet дочерние страницы просто не появятся — классическая ловушка. Index route задаёт страницу по умолчанию, когда пользователь открывает родительский путь без суффикса.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Query string (?sort=date&tab=comments) описывает фильтры и вкладки, не меняя структуру пути. useSearchParams даёт к ним доступ в React-стиле. useLocation полезен для breadcrumbs и для передачи временного state при navigate('/path', { state: { from: 'list' } }). В React Router 6.4+ useMatches помогает строить цепочку навигации из дерева маршрутов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель вложенных маршрутов — русская матрёшка: родительский Route рендерит свой layout, а <Outlet /> — это буквально дыра в этом layout, куда React Router подставляет компонент дочернего маршрута. Если у /blog есть общий сайдбар с категориями, а /blog/:slug показывает конкретный пост, то сайдбар рендерится один раз на уровне родителя и не размонтируется при переходе между постами — меняется только содержимое outlet.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эта модель прямо переносится на Dashboard недели 14: общий Layout с навигацией остаётся смонтированным, пока пользователь переключается между /tasks, /weather и /settings — размонтируется и монтируется заново только содержимое конкретной страницы. То же самое почти в любом реальном приложении с админкой: общая рамка интерфейса не должна перерисовываться при переходе между разделами.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: URL /blog/react-hooks-guideslug в useParams() придёт строкой \"react-hooks-guide\", и если это на самом деле числовой id поста (/blog/42), useParams().id всё равно будет строкой \"42\", а не числом 42. Сравнение id === 42 без Number(id) всегда будет false, хотя внешне всё выглядит правильно — классическая ловушка, о которой явно предупреждают «Ловушки» этого дня.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — полагать, что если родительский Route определён, дочерние страницы появятся «автоматически». Без явного <Outlet /> в JSX родительского компонента React Router прекрасно вычисляет, какой маршрут совпал, но рендерить его содержимое ему буквально некуда — сайдбар покажется, а сам пост — нет, и разработчик потратит время на поиск несуществующего бага в дочернем компоненте, хотя проблема в layout на уровень выше. В практике дня именно это нужно проверить в первую очередь при вёрстке /blog с сайдбаром категорий и вложенной страницей поста.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: путь описывает «где», query — «как показать»; параметры маршрута всегда строки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. /blog — список постов, /blog/:slug — детальная страница
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Данные постов — mock JSON или JSONPlaceholder
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Breadcrumbs: Home → Blog → Post Title
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Query ?sort=date — сортировка списка
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Несуществующий slug → страница «Не найдено»
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Nested layout для /blog с sidebar категорий
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. useSearchParams для tab: ?tab=comments
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] useParams корректно читает :slug

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Несуществующий slug → страница «Не найдено»

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Breadcrumbs обновляются при навигации

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. /blog — список постов, /blog/:slug — детальная страница
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Данные постов — mock JSON или JSONPlaceholder
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Breadcrumbs: Home → Blog → Post Title
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Query ?sort=date — сортировка списка
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-13\n\ngit add src/pages/blog/\n\ngit commit -m "week-13 day-86: динамические маршруты и breadcrumbs"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Параметр :id всегда string — нужен Number(id) или валидация

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Забытый <Outlet /> в layout — дочерние страницы не рендерятся

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 87 (Ср): Custom Hooks — переиспользование логики

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio SPA

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Custom hook — обычная функция с префиксом use, внутри которой вызываются другие хуки. Она не добавляет новых возможностей React, а выносит повторяющуюся логику из компонентов: синхронизацию с localStorage, загрузку данных, debounce ввода. Компонент остаётся про UI, хук — про поведение.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Типичный useLocalStorage(key, initial) комбинирует useState и useEffect: при изменении state значение пишется в storage, при монтировании — читается обратно. Оборачивай JSON.parse в try/catch — битые данные не должны ронять приложение. useFetch(url) инкапсулирует три состояния (loading, error, data) и избавляет каждую страницу от копипасты useEffect.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        useDebounce(value, delay) откладывает обновление: пока пользователь печатает в поиске, тяжёлая фильтрация не запускается на каждый символ. Правила хуков действуют и внутри custom hook — нельзя вызывать хуки условно. Возвращай объект { data, loading } или tuple, но придерживайся одного стиля в проекте.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель custom hook: это не мини-компонент, а способ переиспользовать «поведение» без переиспользования UI. Хорошая аналогия — рецепт: useLocalStorage(key, initial) — это рецепт «состояние + синхронизация с storage», который можно применить к любым данным (тема, задачи, черновик формы), просто передав другой ключ. Важно, что каждый вызов хука создаёт полностью независимый экземпляр состояния: два компонента, вызвавшие useLocalStorage('theme', 'light') и useLocalStorage('draft', ''), не делят между собой ничего, кроме одинаковой логики внутри.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это прямо готовит к неделе 14, где почти всё приложение строится вокруг custom hooks: useTasks инкапсулирует CRUD и persist, а Dashboard и страница /tasks используют один и тот же хук вместо копирования логики в двух местах. Такой подход — стандартная практика в реальных React-кодовых базах, а не учебное упражнение.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример переиспользования: useLocalStorage из этого дня одинаково подходит и для theme (день 88, Context), и для tasks (неделя 14) — меняется только ключ и тип данных, логика синхронизации с localStorage и обработка битого JSON через try/catch не дублируется.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — путать custom hook с компонентом из-за префикса use и думать, что он должен возвращать JSX. На самом деле custom hook — это обычная функция, которая возвращает данные и функции (объект или массив), а не разметку; она не рендерит ничего сама по себе, только управляет состоянием и эффектами, которые уже само использующий её компонент решает, как отобразить. Ещё одна ошибка — забыть, что правила хуков (порядок вызова, только на верхнем уровне) действуют и внутри custom hook: если внутри useDebounce условно вызвать useEffect, это сломает тот же механизм позиционного сопоставления, что и в обычном компоненте — именно поэтому «Ловушки» дня отдельно упоминают запрет условных вызовов хуков.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: custom hook извлекает логику, а не UI; правила хуков обязательны внутри него.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реализуй useLocalStorage с JSON parse/stringify
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. useFetch(url) — возвращает { data, loading, error, refetch }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. useDebounce(value, 300) — для поля поиска в FilterableList
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Покрой хуки простыми тестами вручную (console + checklist)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. useMediaQuery('(min-width: 768px)') — responsive hook
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Вынеси хуки в src/hooks/ с index re-export
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. JSDoc/TSDoc для публичного API каждого хука
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Хуки в папке src/hooks/

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] useLocalStorage работает после F5

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] useDebounce уменьшает количество фильтраций

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реализуй useLocalStorage с JSON parse/stringify
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. useFetch(url) — возвращает { data, loading, error, refetch }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. useDebounce(value, 300) — для поля поиска в FilterableList
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Покрой хуки простыми тестами вручную (console + checklist)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-13\n\ngit add src/hooks/\n\ngit commit -m "week-13 day-87: useLocalStorage, useFetch и useDebounce"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Условный вызов хуков внутри custom hook — нарушение Rules of Hooks

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          useLocalStorage без try/catch при битом JSON в storage

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 88 (Чт): Context API — глобальное состояние

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio SPA

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Prop drilling — передача props через пять уровней дерева — быстро превращает код в лабиринт. Context API даёт альтернативу: Provider в корне публикует значение, любой потомок читает его через useContext без промежуточных компонентов. Классические кандидаты: тема оформления, язык интерфейса, данные текущего пользователя.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        createContext(defaultValue) создаёт контекст; default нужен для подсказок в dev и как fallback, если забыли Provider. Разделяй контексты по доменам: ThemeContext отдельно от UserContext, иначе смена темы перерисует всё дерево, включая компоненты, которым нужен только user. Оборачивай value Provider в useMemo, если передаёшь объект или функции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Context не заменяет локальный state и не является полноценным store. Документация React предупреждает: не тащи в Context часто меняющиеся данные. Для сложного глобального state комбинация Context + useReducer — разумный следующий шаг, но для учебного проекта двух отдельных контекстов (theme + user) достаточно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель Context — это broadcast-канал для целого поддерева: Provider публикует значение один раз в корне, и любой компонент внутри, независимо от глубины вложенности, может подписаться на него через useContext, как будто настроившись на нужную «радиоволну», без необходимости, чтобы каждый промежуточный компонент знал об этом значении и передавал его дальше через props.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эта модель прямо используется в дне 89 этой же недели для AuthContext (сессия пользователя видна на любом маршруте без drilling через каждый layout) и станет ещё важнее на неделе 14, где ThemeContext и UserContext должны быть видны одновременно и в Dashboard, и в Settings, и в шапке навигации — трём совершенно разным веткам дерева компонентов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: переключатель темы на странице /settings меняет theme в ThemeContext; хедер на / и карточки на /tasks, ни один из которых не связан прямым родительско-дочерним отношением с формой настроек, мгновенно перерисовываются с новым классом dark — потому что все они подписаны на один и тот же Provider, а не потому что кто-то явно передал им новое значение через props.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — воспринимать Context как замену полноценного стейт-менеджера и пытаться засунуть туда вообще весь state приложения одним большим объектом. Проблема не только концептуальная, но и практическая: при таком подходе изменение любого поля (даже никак не связанного с большинством потребителей) вызывает ререндер всех компонентов, подписанных на этот Context, потому что React сравнивает ссылку на весь объект value, а не отдельные поля внутри него. Именно поэтому день явно требует разделять ThemeContext и UserContext — смена имени пользователя не должна лишний раз перерисовывать компоненты, которым нужна только тема. Это ровно та дисциплина, которую нужно соблюсти в практике: два независимых провайдера, а не один «God Context» на всё приложение.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: Context — для редко меняющихся глобальных данных; разделяй провайдеры и мемоизируй value.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. ThemeContext: theme, toggleTheme, CSS-класс dark на <html>
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. UserContext: имя пользователя, setName — форма в Settings
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Потребители на разных страницах без prop drilling
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Вынеси Provider в App.tsx один раз
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Persist theme в localStorage через useEffect в Provider
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Custom hook useTheme() — обёртка над useContext
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь: смена темы на /settings отражается на /
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тема сохраняется в localStorage

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Минимум 3 компонента используют Context без промежуточных props

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Default value в createContext для dev-подсказок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. ThemeContext: theme, toggleTheme, CSS-класс dark на <html>
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. UserContext: имя пользователя, setName — форма в Settings
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Потребители на разных страницах без prop drilling
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Вынеси Provider в App.tsx один раз
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-13\n\ngit add src/contexts/\n\ngit commit -m "week-13 day-88: ThemeContext и UserContext"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Один Context на всё приложение — лишние ререндеры при любом изменении

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Забытый Provider — useContext возвращает default, баги «молча»

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 89 (Пт): Комбинация Router + Context + Hooks

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio SPA

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        На этой неделе складываются три слоя: Router отвечает за URL, Context — за глобальное состояние (auth, theme), custom hooks — за переиспользуемую логику. Protected route — тонкая обёртка: если в AuthContext нет пользователя, рендерится <Navigate to=\"/login\" replace />, иначе — дочерняя страница.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Mock-авторизация без реального API — нормальная ступень обучения: сохраняй объект user в localStorage, восстанавливай при старте. Без persist пользователь «разлогинится» после F5. Logout должен атомарно очистить Context, storage и перенаправить на публичную страницу через useNavigate или декларативный <Navigate>.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Разделяй ответственность: форма логина — controlled inputs; проверка доступа — в ProtectedRoute; данные сессии — в Context. location.state позволяет передать, откуда пришёл пользователь, чтобы после login вернуть его на исходную страницу, а не всегда на /dashboard.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель сегодняшнего дня — три независимых слоя, которые взаимодействуют, но не смешиваются: Router отвечает на вопрос «где мы» (URL → компонент), Context — «что мы знаем» (авторизован ли пользователь, какая тема), custom hooks — «как это переиспользуется» (логика внутри useLocalStorage, применённая теперь к сессии). ProtectedRoute — это gatekeeper на стыке первых двух слоёв: он не хранит состояние сам, а лишь читает AuthContext и решает, пропустить дальше к маршруту или подменить его на <Navigate to=\"/login\" />.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Этот паттерн — не учебная условность, а форма, в которой строятся почти все продакшен-приложения: на неделях 20+ появится настоящий backend с JWT-токенами, но структура останется той же — AuthContext будет хранить не мок-пользователя, а результат проверки токена, а ProtectedRoute не изменится вообще. Понимание сегодняшней архитектуры экономит недели путаницы позже, когда вместо мока появится реальный API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример UX-цепочки: неавторизованный пользователь пытается открыть /dashboard, ProtectedRoute перенаправляет на /login, попутно сохраняя исходный путь через location.state = { from: '/dashboard' }; после успешного (мок) логина navigate(state?.from ?? '/dashboard', { replace: true }) возвращает его именно туда, куда он изначально шёл, а не на дефолтную страницу — мелкая деталь, которая сильно улучшает ощущение от приложения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Важная оговорка, которую стоит проговорить явно, чтобы не сформировать ложное чувство защищённости: client-side ProtectedRoute — это UX-фильтр, а не механизм безопасности. Весь JS-код, включая проверку if (!user), выполняется в браузере пользователя и может быть обойдён (просто отредактирован в DevTools) кем угодно с базовыми навыками. Реальная защита данных всегда происходит на сервере, который должен сам проверять права на каждый запрос — client-side роутинг лишь скрывает UI, но никогда не заменяет серверную авторизацию. Это прямо связано с пунктом «Ловушки»: сегодняшний ProtectedRoute проверяет только наличие объекта user, а не валидность токена — эта тема вернётся на неделе 20 уже с настоящим backend.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: protected route проверяет сессию на уровне маршрута; persist в storage переживает перезагрузку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. AuthContext с user, login, logout (mock, без реального API)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. ProtectedRoute — children или <Navigate to=\"/login\" />
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. /dashboard — только для авторизованных
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. После login — navigate('/dashboard', { replace: true })
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Страница /login — controlled form, mock credentials
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Persist user в localStorage — переживает F5
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Header: кнопка Logout на всех страницах
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Неавторизованный пользователь не видит /dashboard

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Logout очищает Context и редиректит на /

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Login form — controlled inputs

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. AuthContext с user, login, logout (mock, без реального API)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. ProtectedRoute — children или <Navigate to=\"/login\" />
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. /dashboard — только для авторизованных
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. После login — navigate('/dashboard', { replace: true })
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-13\n\ngit add src/contexts/AuthContext.tsx src/components/ProtectedRoute.tsx\n\ngit commit -m "week-13 day-89: AuthContext и protected routes"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Хранение «авторизации» только в state без persist — F5 разлогинивает

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Protected route проверяет только наличие объекта, не валидность token (позже на нед. 20)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 90 (Сб): Оптимизация и структура проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio SPA

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        К концу недели проект обрастает папками: pages/, components/, hooks/, contexts/, utils/. Предсказуемая структура важнее идеальной: новый разработчик (или ты через месяц) должен за минуту найти, где живут маршруты и где — хуки. ARCHITECTURE.md фиксирует решения, а не дублирует README с командами запуска.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Оптимизация в React начинается с измерения, а не с useMemo на каждой функции. Profiler в DevTools показывает лишние ререндеры. React.lazy + Suspense разбивают bundle: тяжёлая страница /admin загружается только при переходе. useMemo оправдан для дорогих вычислений; useCallback — когда передаёшь колбэк в React.memo-компонент.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Barrel exports (index.ts) ускоряют импорты, но могут ухудшить tree-shaking — используй осознанно. useCallback без memoized child бесполезен. Преждевременная мемоизация усложняет код без выигрыша: сначала работающее приложение, потом профилирование, потом точечные правки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель оптимизации в React: сначала измерить, потом чинить, а не наоборот. Profiler в DevTools отвечает на вопрос «какой компонент действительно долго рендерится и почему», превращая интуитивные догадки в конкретные цифры (миллисекунды на конкретный commit). Без этого шага легко потратить время на мемоизацию компонента, который и так рендерится за доли миллисекунды, пропустив реальную проблему в другом месте дерева.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это умение станет практически необходимым на неделе 14: Dashboard одновременно рендерит статистику, список задач и виджет погоды — без структуры и точечной оптимизации лишние ререндеры будут накапливаться незаметно, а профилирование покажет, где именно. Тот же навык прямо пригодится на реальной работе и часто спрашивается на технических собеседованиях как «как бы ты нашёл причину лагов в React-приложении».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример пользы lazy loading: страница /admin нужна редкому проценту пользователей, но её код (таблицы, формы, графики) может весить сотни килобайт. React.lazy(() => import('./pages/Admin')) в паре с <Suspense> гарантирует, что этот код не попадёт в основной bundle и не замедлит первую загрузку для обычного посетителя, который никогда не откроет /admin.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — воспринимать useMemo и useCallback как «бесплатную» оптимизацию, которую можно расставлять по коду на автомате. На самом деле у мемоизации есть своя цена: React должен хранить предыдущие зависимости и сравнивать их на каждом рендере, и если сравниваемое значение вычисляется быстрее, чем сам массив зависимостей проверяется, мемоизация не ускоряет код, а замедляет и усложняет его без всякой выгоды. Именно поэтому «Ловушки» дня прямо называют преждевременную оптимизацию проблемой — практика дня требует сначала реорганизовать структуру папок и задокументировать архитектуру, и только потом точечно применять useMemo там, где Profiler реально показал узкое место (например, фильтрация 1000+ элементов), а не «на всякий случай» по всему коду.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: оптимизируй после профилирования; lazy routes уменьшают начальный bundle.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реорганизуй проект недели по папкам
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Lazy-load страницу /admin с fallback-спиннером
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. useMemo для дорогой фильтрации списка (1000+ элементов — mock)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Документируй архитектуру в ARCHITECTURE.md (1 страница)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. React.memo на TodoItem — измерь, есть ли выгода
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Suspense boundary с понятным fallback UI
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Проверь bundle size после lazy loading
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Импорты страниц через React.lazy

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет useMemo/useCallback «на всякий случай» без причины

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Понятная структура папок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реорганизуй проект недели по папкам
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Lazy-load страницу /admin с fallback-спиннером
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. useMemo для дорогой фильтрации списка (1000+ элементов — mock)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Документируй архитектуру в ARCHITECTURE.md (1 страница)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-13\n\ngit add ARCHITECTURE.md src/pages/\n\ngit commit -m "week-13 day-90: lazy routes, useMemo и структура"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Преждевременная оптимизация — сначала работающий код, потом профилирование

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          useCallback без memoized child — бесполезен

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 91 (Вс): Ревью паттернов React

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Portfolio SPA

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        За семь дней ты собрал многостраничное SPA с роутингом, глобальным state и переиспользуемыми хуками. Полезно явно сравнить инструменты: локальный state для UI формы, lifting state когда нужно двум соседям, custom hook для логики, Context для редких глобальных данных, внешний store (Zustand/Redux) — когда Context разрастается.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Error Boundary ловит ошибки рендеринга в дочерних компонентах и показывает fallback вместо белого экрана. Оберни <Routes> или отдельные страницы, чтобы сбой на /blog/:slug не убивал всё приложение. Boundary не ловит ошибки в event handlers и async-коде — только синхронный render.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Перед деплоем проверь client-side routing: хостинг должен отдавать index.html на все пути. Portfolio SPA — витрина навыков недели: осмысленные коммиты за 7 дней, preview URL, README с картой маршрутов. Скелет Dashboard на неделю 14 логично начать с тех же паттернов Layout + Context + hooks.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель для выбора инструмента state — это шкала по двум осям: сколько компонентов читают/меняют значение и как часто оно меняется. Локальный useState — для UI одного компонента (открыт ли dropdown). Lifting state up — когда двум-трём соседям на одном уровне нужно одно значение (неделя 12, день 83). Context — когда значение нужно широко по дереву, но меняется редко (тема, сессия). Внешний store (Zustand, Redux, Jotai) — когда часто меняющихся глобальных данных становится много и Context начинает вызывать заметные лишние ререндеры. Эта шкала — не догма, а рабочий чеклист, который стоит прогонять в голове при старте каждой новой фичи.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Именно это умение станет решающим на неделе 14 при проектировании Dashboard (задачи — в custom hook или Context? тема — в Context, а фильтр списка — локальный useState?), а затем и в любом будущем проекте, включая приложения с backend, где к этой шкале добавится ещё один вопрос — что хранить на клиенте, а что запрашивать заново с сервера.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример выбора: поле поиска, фильтрующее список внутри одной страницы, — это локальный state или, максимум, lifting state между двумя соседними компонентами; заворачивать его в Context было бы избыточно и создало бы недокументированную глобальную связь там, где хватило бы пропса.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать, что «чем более глобально хранится состояние, тем безопаснее и удобнее», и по умолчанию тянуть данные в Context «на всякий случай», даже если ими пользуется один компонент. Другое похожее заблуждение — думать, что Error Boundary ловит вообще любые ошибки; на деле она перехватывает только синхронные ошибки рендеринга дочерних компонентов и не ловит исключения в обработчиках событий или внутри async кода (там нужен обычный try/catch). Оба заблуждения важно развеять перед финализацией Portfolio SPA: Error Boundary в практике дня оборачивает именно <Routes>, чтобы сбой рендера одной страницы (например, из-за некорректных данных :slug) не обрушивал всё приложение целиком, а не как универсальная страховка от любых ошибок.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: выбор инструмента state — по частоте изменений и глубине дерева, не «всё в Context».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Добавь простой Error Boundary вокруг <Routes>
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Пройди чеклист своего многостраничного приложения
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Запиши ответы: «Когда Context, когда custom hook, когда lifting state?»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Подготовь skeleton для Dashboard (неделя 14)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Финализируй Portfolio SPA — все маршруты и hooks
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Deploy preview на Vercel/Netlify
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-13-done
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Error Boundary ловит ошибку в дочернем компоненте

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Написан план страниц Dashboard: /, /tasks, /weather, /settings

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Git commit за каждый день недели

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Добавь простой Error Boundary вокруг <Routes>
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Пройди чеклист своего многостраничного приложения
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Запиши ответы: «Когда Context, когда custom hook, когда lifting state?»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Подготовь skeleton для Dashboard (неделя 14)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-13\n\ngit add .\n\ngit commit -m "week-13 day-91: Error Boundary и Portfolio SPA deploy"\n\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Personal Portfolio SPA (промежуточный, перед Dashboard). Подробное ТЗ: docs/projects.md — Неделя 13.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. \n

                                                                                                                                                                                                                          Роутинг: Home, Projects, Project Detail :id, Blog, Contact

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. \n

                                                                                                                                                                                                                          ThemeContext + useLocalStorage

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. \n

                                                                                                                                                                                                                          Custom hooks: useFetch для GitHub API (repos), useDebounce для поиска проектов

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. \n

                                                                                                                                                                                                                          Protected /admin с mock-auth

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. \n

                                                                                                                                                                                                                          Адаптивная навигация (бургер-меню на мобиле)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] ≥ 5 маршрутов, nested layout

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] ≥ 2 custom hooks, ≥ 1 Context

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] 404, loading states, error handling

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] GitHub API repos на странице Projects

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Деплой на GitHub Pages или Vercel (preview)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] README с URL и описанием маршрутов

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тег week-13-done

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Чем Link отличается от обычной <a>?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Как передать query-параметры и прочитать их?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Зачем custom hook, если можно просто функцию?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Когда Context вызывает лишние ререндеры?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Как защитить маршрут от неавторизованного доступа?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Portfolio SPA** в `learning-log/week-13/`, осмысленная Git-история, тег `week-13-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nReact Router, Context, custom hooks\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-13-day-85", "label": "День 85 (Пн): React Router — основы"}, {"id": "week-13-day-86", "label": "День 86 (Вт): Динамические маршруты и nested routes"}, {"id": "week-13-day-87", "label": "День 87 (Ср): Custom Hooks — переиспользование логики"}, {"id": "week-13-day-88", "label": "День 88 (Чт): Context API — глобальное состояние"}, {"id": "week-13-day-89", "label": "День 89 (Пт): Комбинация Router + Context + Hooks"}, {"id": "week-13-day-90", "label": "День 90 (Сб): Оптимизация и структура проекта"}, {"id": "week-13-day-91", "label": "День 91 (Вс): Ревью паттернов React"}, {"id": "week-13-project", "label": "Проект недели"}, {"id": "week-13-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-13-review", "label": "Проверь себя"}], "text": "Неделя 13: React Router, хуки, Context Цель недели: построить многостраничное SPA с переиспользуемой логикой и глобальным состоянием. Литература: React Router , react.dev — Context , react.dev — Reusing Logic , React Router Tutorial , useDebounce patterns Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-13/ День 85 (Пн): React Router — основы Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к Portfolio SPA Теория Одностраничное приложение (SPA) живёт в одной HTML-странице, но пользователь ожидает поведение «настоящего сайта»: разные URL, кнопка «Назад» в браузере, закладки на конкретные экраны. React Router решает эту задачу на клиенте: при…"} \ No newline at end of file diff --git a/docs/weeks/14.json b/docs/weeks/14.json index d672240..5f684b1 100644 --- a/docs/weeks/14.json +++ b/docs/weeks/14.json @@ -1 +1 @@ -{"id": "week-14", "title": "Frontend SPA", "fullTitle": "Неделя 14: Frontend Capstone — React Dashboard", "html": "

                                                                                                                                                                                                                        Неделя 14: Frontend Capstone — React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: собрать полноценное SPA-приложение, объединяющее все навыки React-фронтенда.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература: react.dev, React Router, OpenWeatherMap API, Vite Env Variables, web.dev — Web Vitals

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git: минимум 1 осмысленный коммит каждый день в learning-log/week-14/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 92 (Пн): Архитектура и скелет проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Frontend capstone начинается с архитектуры, а не с кода. Прежде чем писать компоненты, зафиксируй страницы (/, /tasks, /weather, /settings), источники данных (localStorage, Context, внешний API) и границы ответственности модулей. Хороший скелет экономит дни рефакторинга на середине недели.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Vite отделяет переменные окружения по префиксу: только VITE_* попадают в клиентский bundle. API-ключи OpenWeather никогда не хардкодь — import.meta.env.VITE_WEATHER_API_KEY и .env.example без реальных значений. Файл .env в .gitignore, иначе ключ утечёт на GitHub.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура папок: pages/ для маршрутов, components/ui/ для переиспользуемых кнопок и карточек, hooks/ и contexts/ для логики, services/ для HTTP. Mobile-first CSS с CSS-переменными для темы закладывает адаптив с первого дня. Отдельная папка learning-log/week-14/ с чистой git-историей — привычка, которая пригодится в capstone.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: спланируй страницы и state до кода; секреты — только через VITE_* и .env.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm create vite@latest week-14 -- --template react-ts в learning-log/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Установи react-router-dom, настрой Layout + 4 маршрута
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Заглушки страниц: Dashboard, Tasks, Weather, Settings
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. App.css — CSS-переменные для светлой/тёмной темы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. .env.example с VITE_WEATHER_API_KEY=
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Sidebar + main content area — responsive skeleton
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. ARCHITECTURE.md — план страниц и state на 1 страницу
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] 4 маршрута с общим Layout

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Адаптивная sidebar/nav

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] .env в .gitignore

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm create vite@latest week-14 -- --template react-ts в learning-log/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Установи react-router-dom, настрой Layout + 4 маршрута
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Заглушки страниц: Dashboard, Tasks, Weather, Settings
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. App.css — CSS-переменные для светлой/тёмной темы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-14\n\ngit add .\n\ngit commit -m "week-14 day-92: скелет Dashboard, Layout и 4 маршрута"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          API-ключ в коде — утечка при push на GitHub

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Монолитный App.jsx на 500 строк — сразу дроби на модули

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 93 (Вт): Dashboard — статистика и карточки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Главная страница Dashboard — витрина приложения: несколько независимых виджетов в единой сетке. Композиция через мелкие компоненты (StatCard, Grid) проще в поддержке, чем один монолитный Dashboard.tsx. Каждая карточка получает данные через props или hooks и не знает о соседях.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CSS Grid с repeat(auto-fit, minmax(240px, 1fr)) даёт адаптив без десятка media queries: на мобиле одна колонка, на desktop — четыре. Статистика задач — derived state: вычисляй total и done из массива tasks, не дублируй в отдельном useState, иначе рассинхрон неизбежен.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        useMemo здесь оправдан, если фильтрация или агрегация затратна. Skeleton-карточки при загрузке предотвращают layout shift (CLS). Для иконок предпочитай inline SVG или библиотеку вроде lucide-react; у декоративных иконок добавляй aria-hidden, у смысловых — aria-label.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: статистика — производная от данных tasks, не отдельный источник правды.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Главная / — 4 карточки: задачи (total/done), погода, имя user, дата
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Данные задач из useLocalStorage('tasks')
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Приветствие из UserContext
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Responsive grid: 1 колонка мобила → 2 → 4 на desktop
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Компонент StatCard с title, value, icon, trend (опционально)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Форматирование даты через Intl.DateTimeFormat
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Empty state на карточке задач: «Добавьте первую задачу»
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Карточки обновляются при изменении tasks

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет layout shift при загрузке

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Контраст текста ≥ WCAG AA (проверь в DevTools)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Главная / — 4 карточки: задачи (total/done), погода, имя user, дата
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Данные задач из useLocalStorage('tasks')
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Приветствие из UserContext
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Responsive grid: 1 колонка мобила → 2 → 4 на desktop
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-14\n\ngit add src/pages/Dashboard.tsx src/components/ui/StatCard.tsx\n\ngit commit -m "week-14 day-93: Dashboard stats и StatCard grid"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Хардкод статистики вместо вычисления из реальных данных

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Иконки без текстовой альтернативы для screen readers

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 94 (Ср): Tasks — CRUD и фильтрация

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Страница Tasks — сердце Dashboard: здесь проверяется, насколько чисто организован state. Custom hook useTasks становится единственным источником правды: и Dashboard, и /tasks читают одни данные через один hook (или Context-обёртку над ним). Дублирование логики в двух страницах — прямой путь к багам.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CRUD в React всегда иммутабелен: setTasks(prev => [...prev, newTask]), toggle через map, delete через filter. Фильтры и сортировка — derived state от tasks + filter + sortBy, а не отдельные копии списка. Стабильный key={task.id} обязателен: key={index} ломает фокус и анимации при удалении.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Расширенная модель (приоритет, дедлайн) учит проектировать типы заранее. Просроченные задачи — вычисляемое свойство: deadline < today. Поиск с debounce (hook из недели 13) снижает нагрузку при больших списках. Persist в localStorage через hook сохраняет данные между сессиями.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: один useTasks на всё приложение; фильтры — derived state, не копия списка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Страница /tasks: форма добавления, список, фильтры (all/active/done)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Редактирование inline или modal
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Приоритет (цветовая метка) и дедлайн
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сортировка: по дате, приоритету
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Поиск по тексту задачи — filter + debounce
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. useTasks hook с persist в localStorage
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Подсветка просроченных задач (deadline < today)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] CRUD полностью работает, persist в localStorage

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Фильтры не ломают редактирование

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] key стабильный (id), не index

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Страница /tasks: форма добавления, список, фильтры (all/active/done)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Редактирование inline или modal
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Приоритет (цветовая метка) и дедлайн
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сортировка: по дате, приоритету
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-14\n\ngit add src/hooks/useTasks.ts src/pages/Tasks.tsx\n\ngit commit -m "week-14 day-94: useTasks, CRUD и фильтры"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          key={index} при удалении — скачки фокуса и баги

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Дублирование логики tasks в Dashboard и Tasks page

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 95 (Чт): Weather — интеграция внешнего API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Интеграция внешнего API — переход от учебного localStorage к реальному асинхронному миру. OpenWeather Current Weather API принимает город и ключ, возвращает температуру, влажность, описание и код иконки. Единицы (metric / imperial) лучше брать из Settings, а не хардкодить.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Три UI-состояния обязательны: loading (skeleton или spinner), error (сообщение + retry), success (данные). Проверяй res.ok — 401 (битый ключ), 404 (город не найден) и 429 (лимит free tier) должны давать понятный текст, а не «белый экран смерти». Кэш в sessionStorage на 10 минут с timestamp экономит квоту API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        useFetch или dedicated weatherApi.ts изолируют HTTP от компонента. Мини-виджет на Dashboard и полная страница /weather должны использовать один hook — иначе дублируется логика кэша. Debounce или submit по кнопке: запрос на каждый keystroke в поле города быстро исчерпает лимит.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: API-слой отдельно от UI; loading/error/success — на каждом экране с данными.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Страница /weather: input города, кнопка поиска
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Отображение: температура, описание, иконка, влажность, ветер
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Сохрани последний город в localStorage
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Обработка неверного API key и лимита запросов
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Кэш ответа в sessionStorage с timestamp
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Мини-виджет погоды на Dashboard (тот же hook)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Retry кнопка при сетевой ошибке
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Loading / error / success states

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Кэш 10 мин — повторный запрос не уходит в сеть

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Город по умолчанию из Settings

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Страница /weather: input города, кнопка поиска
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Отображение: температура, описание, иконка, влажность, ветер
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Сохрани последний город в localStorage
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Обработка неверного API key и лимита запросов
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-14\n\ngit add src/pages/Weather.tsx src/services/weatherApi.ts\n\ngit commit -m "week-14 day-95: OpenWeather API и кэш"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Запрос на каждый keystroke — debounce или submit по кнопке

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Не обработанный res.ok === false — «белый экран смерти»

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 96 (Пт): Settings — Context и персонализация

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Settings — центр персонализации и хороший тест на Context. Разделяй ThemeContext и UserContext: смена имени пользователя не должна перерисовывать подписчиков темы. Controlled form синхронизирует поля с state; изменения сразу отражаются на Dashboard и Weather без перезагрузки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        useId() генерирует стабильные id для связки label + input — важно для доступности и для избежания коллизий при нескольких формах. Валидация на клиенте (имя ≥ 2 символов, город не пустой) улучшает UX, даже если позже добавишь серверную проверку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Деструктивные действия («Сбросить настройки») требуют confirm dialog. Persist через localStorage в Provider или custom hook. Бонус export/import JSON — учит сериализовать state целиком. Toast при успешном сохранении даёт обратную связь без блокировки UI.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: Settings — single source для темы, города и единиц; разделяй контексты по доменам.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. /settings: имя, город по умолчанию, переключатель темы, единицы °C/°F
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Изменения сразу отражаются на Dashboard и Weather
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Кнопка «Сбросить настройки» с confirm dialog
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Экспорт/импорт настроек JSON (bonus)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. useId() для всех полей формы
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Валидация с сообщениями под полями
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Toast при успешном сохранении
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тема применяется ко всему приложению

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Настройки переживают F5

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Form labels связаны с inputs

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. /settings: имя, город по умолчанию, переключатель темы, единицы °C/°F
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Изменения сразу отражаются на Dashboard и Weather
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Кнопка «Сбросить настройки» с confirm dialog
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Экспорт/импорт настроек JSON (bonus)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-14\n\ngit add src/contexts/ src/pages/Settings.tsx\n\ngit commit -m "week-14 day-96: Settings, Context и персонализация"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Один Context на theme + user + settings — лишние ререндеры

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Сброс без confirm — случайная потеря данных

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 97 (Сб): Полировка UX и адаптив

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Полировка UX отличает «работает» от «приятно пользоваться». Адаптив — не опция: начни с 320px ширины, убедись, что нет horizontal scroll. Hamburger-меню на мобиле превращает sidebar в drawer; на desktop — постоянная навигация. Touch targets ≥ 44px снижают mis-tap на телефоне.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Доступность: :focus-visible вместо outline: none, tab-навигация по всем интерактивным элементам, контраст текста ≥ WCAG AA (проверь в DevTools). prefers-reduced-motion уважает настройки ОС — отключи лишние анимации для пользователей с вестибулярными расстройствами.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Toast-уведомления — лёгкий паттерн feedback при CRUD. Empty states («Нет задач — добавьте первую») лучше пустой таблицы. Lighthouse audit: цель Performance ≥ 80, Accessibility ≥ 90. Микро-анимации через CSS transitions добавляют «живости» без тяжёлых библиотек.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: a11y и mobile-first — часть Definition of Done, не «потом».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Мобильное меню (hamburger → drawer)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Toast-уведомления: задача добавлена, ошибка API
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Empty state: «Нет задач — добавьте первую»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Lighthouse audit — цель Performance ≥ 80, Accessibility ≥ 90
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Focus styles на всех интерактивных элементах
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Проверка на 320px ширине — нет horizontal scroll
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. CSS transitions на hover/focus (с reduced-motion fallback)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Tab-навигация по всем интерактивным элементам

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет горизонтального скролла на 320px

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Lighthouse Accessibility ≥ 90

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Мобильное меню (hamburger → drawer)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Toast-уведомления: задача добавлена, ошибка API
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Empty state: «Нет задач — добавьте первую»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Lighthouse audit — цель Performance ≥ 80, Accessibility ≥ 90
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-14\n\ngit add src/components/\n\ngit commit -m "week-14 day-97: mobile nav, toast и a11y polish"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          outline: none без замены — ломает a11y

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Фиксированная sidebar на мобиле закрывает контент

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 98 (Вс): Тестирование вручную и документация

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        React Dashboard — крупнейший фронтенд-проект до бэкенда; день ревью фиксирует качество, а не добавляет фичи. Пройди user flow глазами новичка: первый визит → настройки → задачи → погода → смена темы → F5. Каждый шаг должен работать без инструкции в README.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Production build (npm run build) часто выявляет warnings, которые dev-сервер скрывает: неиспользуемые импорты, env без fallback. Deploy на Vercel/Netlify требует настройки SPA fallback для client-side routes. README с GIF или скриншотами — визитная карточка для портфолио.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Conventional Commits за неделю показывают зрелость: feat:, fix:, docs: в сообщениях. ARCHITECTURE.md обнови финальной схемой state. Этот проект станет основой для full-stack интеграции на неделях 21–22 — чистая структура сейчас сэкономит часы потом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: capstone-качество начинается с README, deploy preview и осмысленной git-истории.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди user flow: первый визит → настройки → задачи → погода → смена темы → F5
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Напиши README с GIF или 3 скриншотами
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. npm run build — исправь warnings
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Deploy preview на Vercel
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Обнови ARCHITECTURE.md — финальная схема state
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Self-review по ревью-чеклисту недели
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-14-done
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Production build без ошибок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] README понятен новичку

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Preview URL в README

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди user flow: первый визит → настройки → задачи → погода → смена темы → F5
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Напиши README с GIF или 3 скриншотами
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. npm run build — исправь warnings
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Deploy preview на Vercel
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-14\n\ngit add README.md ARCHITECTURE.md\n\ngit commit -m "week-14 day-98: README, deploy и React Dashboard capstone"\n\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        React Dashboard SPA — итоговый deliverable недели, крупнейший фронтенд-проект до бэкенда. Подробное ТЗ: docs/projects.md — Неделя 14.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Маршруты: / статистика, /tasks CRUD, /weather API, /settings тема и user. React Router, hooks, Context, адаптив, deploy preview.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Dashboard с live-статистикой из tasks и user context

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Tasks: CRUD, приоритет, дедлайн, фильтры, поиск

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Weather: OpenWeatherMap, кэш, retry, единицы из settings

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Settings: тема, имя, город, export/import (bonus)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Все 4 страницы полностью функциональны

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет prop drilling глубже 2 уровней

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] GitHub repo с понятной историей коммитов (≥ 7 за неделю)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Vercel/Netlify preview работает

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Lighthouse Accessibility ≥ 90

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] .env.example без реальных ключей

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тег week-14-done

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Могу объяснить архитектуру проекта за 2 минуты?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Где хранится state задач и почему именно там?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Как бы добавил авторизацию к этому Dashboard?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Что произойдёт при истечении API-ключа OpenWeather?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Какие 3 улучшения сделал бы в v2?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **React Dashboard** в `learning-log/week-14/`, осмысленная Git-история, тег `week-14-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nПолноценное frontend SPA\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-14-day-92", "label": "День 92 (Пн): Архитектура и скелет проекта"}, {"id": "week-14-day-93", "label": "День 93 (Вт): Dashboard — статистика и карточки"}, {"id": "week-14-day-94", "label": "День 94 (Ср): Tasks — CRUD и фильтрация"}, {"id": "week-14-day-95", "label": "День 95 (Чт): Weather — интеграция внешнего API"}, {"id": "week-14-day-96", "label": "День 96 (Пт): Settings — Context и персонализация"}, {"id": "week-14-day-97", "label": "День 97 (Сб): Полировка UX и адаптив"}, {"id": "week-14-day-98", "label": "День 98 (Вс): Тестирование вручную и документация"}, {"id": "week-14-project", "label": "Проект недели"}, {"id": "week-14-review", "label": "Ревью-чеклист"}], "text": "Неделя 14: Frontend Capstone — React Dashboard Цель недели: собрать полноценное SPA-приложение, объединяющее все навыки React-фронтенда. Литература: react.dev , React Router , OpenWeatherMap API , Vite Env Variables , web.dev — Web Vitals Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-14/ День 92 (Пн): Архитектура и скелет проекта Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к React Dashboard Теория Frontend capstone начинается с архитектуры, а не с кода. Прежде чем писать компоненты, зафиксируй страницы ( / , /tasks , /weather , /settings ), источники данных (localStorage, Context, внешний API) и границы ответственности модулей. Хоро…"} \ No newline at end of file +{"id": "week-14", "title": "Frontend SPA", "fullTitle": "Неделя 14: Frontend Capstone — React Dashboard", "html": "

                                                                                                                                                                                                                        Неделя 14: Frontend Capstone — React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: собрать полноценное SPA-приложение, объединяющее все навыки React-фронтенда.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература: react.dev, React Router, OpenWeatherMap API, Vite Env Variables, web.dev — Web Vitals

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git: минимум 1 осмысленный коммит каждый день в learning-log/week-14/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 92 (Пн): Архитектура и скелет проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Frontend capstone начинается с архитектуры, а не с кода. Прежде чем писать компоненты, зафиксируй страницы (/, /tasks, /weather, /settings), источники данных (localStorage, Context, внешний API) и границы ответственности модулей. Хороший скелет экономит дни рефакторинга на середине недели.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Vite отделяет переменные окружения по префиксу: только VITE_* попадают в клиентский bundle. API-ключи OpenWeather никогда не хардкодь — import.meta.env.VITE_WEATHER_API_KEY и .env.example без реальных значений. Файл .env в .gitignore, иначе ключ утечёт на GitHub.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура папок: pages/ для маршрутов, components/ui/ для переиспользуемых кнопок и карточек, hooks/ и contexts/ для логики, services/ для HTTP. Mobile-first CSS с CSS-переменными для темы закладывает адаптив с первого дня. Отдельная папка learning-log/week-14/ с чистой git-историей — привычка, которая пригодится в capstone.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель дня: архитектура — это чертёж здания, а код — это стройка. Ты же не начинаешь строить дом, пока не решил, сколько этажей, где несущие стены и куда идут трубы. Точно так же час, потраченный на ARCHITECTURE.md с описанием страниц, источников данных и границ модулей, экономит дни переписывания кода в середине недели, когда выяснится, что задачи нужны сразу и на Dashboard, и на /tasks, а состояние для них рассовано по разным местам.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это особенно критично именно для capstone-проекта такого масштаба: впервые за курс собирается приложение с четырьмя полноценными страницами, внешним API и persist-слоем одновременно. Без предварительного плана велик риск «big ball of mud» — кода, который работает, но настолько запутан, что даже автор через три дня не может быстро найти, где лежит логика фильтрации задач.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример решения, которое стоит принять именно сегодня, а не на день 94: задачи должны читаться через один useTasks hook (или Context поверх него), которым пользуются и Dashboard (для статистики), и страница /tasks (для CRUD) — если это не зафиксировать заранее, велик соблазн написать useLocalStorage('tasks') в двух местах независимо, а затем удивляться, почему изменения не синхронизируются.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что .env файл автоматически безопасен просто потому, что не закоммичен явно руками; на самом деле любой файл, случайно не попавший в .gitignore до первого коммита, останется в истории Git навсегда, даже если потом его удалить — поэтому .gitignore с .env нужно создать до, а не после первого git add .. Также важно понимать: VITE_* переменные всё равно оказываются в финальном JS-бандле, видимом любому пользователю в DevTools — это защита от случайного коммита секрета в репозиторий, а не от раскрытия ключа в браузере. Именно поэтому OpenWeather API-ключ, который появится через несколько дней, — не секрет высокого риска, но привычку хранить его через .env.example стоит выработать уже сегодня, при закладке скелета проекта.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: спланируй страницы и state до кода; секреты — только через VITE_* и .env.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm create vite@latest week-14 -- --template react-ts в learning-log/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Установи react-router-dom, настрой Layout + 4 маршрута
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Заглушки страниц: Dashboard, Tasks, Weather, Settings
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. App.css — CSS-переменные для светлой/тёмной темы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. .env.example с VITE_WEATHER_API_KEY=
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Sidebar + main content area — responsive skeleton
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. ARCHITECTURE.md — план страниц и state на 1 страницу
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] 4 маршрута с общим Layout

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Адаптивная sidebar/nav

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] .env в .gitignore

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm create vite@latest week-14 -- --template react-ts в learning-log/
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Установи react-router-dom, настрой Layout + 4 маршрута
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Заглушки страниц: Dashboard, Tasks, Weather, Settings
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. App.css — CSS-переменные для светлой/тёмной темы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-14\n\ngit add .\n\ngit commit -m "week-14 day-92: скелет Dashboard, Layout и 4 маршрута"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          API-ключ в коде — утечка при push на GitHub

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Монолитный App.jsx на 500 строк — сразу дроби на модули

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 93 (Вт): Dashboard — статистика и карточки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Главная страница Dashboard — витрина приложения: несколько независимых виджетов в единой сетке. Композиция через мелкие компоненты (StatCard, Grid) проще в поддержке, чем один монолитный Dashboard.tsx. Каждая карточка получает данные через props или hooks и не знает о соседях.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CSS Grid с repeat(auto-fit, minmax(240px, 1fr)) даёт адаптив без десятка media queries: на мобиле одна колонка, на desktop — четыре. Статистика задач — derived state: вычисляй total и done из массива tasks, не дублируй в отдельном useState, иначе рассинхрон неизбежен.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        useMemo здесь оправдан, если фильтрация или агрегация затратна. Skeleton-карточки при загрузке предотвращают layout shift (CLS). Для иконок предпочитай inline SVG или библиотеку вроде lucide-react; у декоративных иконок добавляй aria-hidden, у смысловых — aria-label.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель Dashboard — это сетка независимых виджетов, каждый из которых «глухой» к соседям: StatCard знает только свои title, value, icon, но ничего не знает о том, что рядом ещё три такие же карточки и откуда вообще берутся данные. Композиция из простых, переиспользуемых кусочков — надёжнее, чем один компонент Dashboard.tsx на 300 строк, где логика статистики, погоды и приветствия перемешаны в одном JSX-дереве.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Этот подход — не специфика учебного проекта, а стандарт для любых аналитических интерфейсов и админ-панелей в индустрии: StatCard, ChartWidget, ActivityFeed — везде один и тот же принцип «глупый переиспользуемый компонент + умный контейнер, который считает данные».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример derived state: карточка «Задачи: 5 из 12 выполнено» не должна хранить total и done в отдельном useState, который нужно вручную обновлять при каждом добавлении/удалении/переключении задачи. Правильно — вычислять const done = tasks.filter(t => t.done).length прямо при рендере: тогда карточка гарантированно не может «отстать» от реальных данных, что бы ни произошло со списком задач.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — «закешировать» подобную статистику в отдельном state ради мнимой оптимизации: якобы пересчитывать filter на каждый рендер дорого. На практике для списков из десятков-сотен задач эта операция занимает доли миллисекунды, а риск рассинхрона (пользователь отметил задачу выполненной, а карточка показывает старое число, потому что забыли обновить отдельный state) — это реальный баг, который случится почти гарантированно. Правило простое: сначала derived state при рендере, и только если Profiler покажет реальную проблему производительности — useMemo вокруг вычисления, но не преждевременно. Это прямо связано с критерием дня «карточки обновляются при изменении tasks» — самый надёжный способ гарантировать это свойство — не хранить копию данных вообще.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: статистика — производная от данных tasks, не отдельный источник правды.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Главная / — 4 карточки: задачи (total/done), погода, имя user, дата
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Данные задач из useLocalStorage('tasks')
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Приветствие из UserContext
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Responsive grid: 1 колонка мобила → 2 → 4 на desktop
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Компонент StatCard с title, value, icon, trend (опционально)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Форматирование даты через Intl.DateTimeFormat
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Empty state на карточке задач: «Добавьте первую задачу»
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Карточки обновляются при изменении tasks

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет layout shift при загрузке

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Контраст текста ≥ WCAG AA (проверь в DevTools)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Главная / — 4 карточки: задачи (total/done), погода, имя user, дата
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Данные задач из useLocalStorage('tasks')
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Приветствие из UserContext
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Responsive grid: 1 колонка мобила → 2 → 4 на desktop
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-14\n\ngit add src/pages/Dashboard.tsx src/components/ui/StatCard.tsx\n\ngit commit -m "week-14 day-93: Dashboard stats и StatCard grid"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Хардкод статистики вместо вычисления из реальных данных

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Иконки без текстовой альтернативы для screen readers

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 94 (Ср): Tasks — CRUD и фильтрация

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Страница Tasks — сердце Dashboard: здесь проверяется, насколько чисто организован state. Custom hook useTasks становится единственным источником правды: и Dashboard, и /tasks читают одни данные через один hook (или Context-обёртку над ним). Дублирование логики в двух страницах — прямой путь к багам.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CRUD в React всегда иммутабелен: setTasks(prev => [...prev, newTask]), toggle через map, delete через filter. Фильтры и сортировка — derived state от tasks + filter + sortBy, а не отдельные копии списка. Стабильный key={task.id} обязателен: key={index} ломает фокус и анимации при удалении.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Расширенная модель (приоритет, дедлайн) учит проектировать типы заранее. Просроченные задачи — вычисляемое свойство: deadline < today. Поиск с debounce (hook из недели 13) снижает нагрузку при больших списках. Persist в localStorage через hook сохраняет данные между сессиями.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель useTasks: это единственная «таблица данных» в приложении, а Dashboard и страница /tasks — просто разные «представления» (views) над одной и той же таблицей, как в базе данных. Ни одна страница не имеет своей копии задач — обе читают из одного hook (напрямую или через Context-обёртку), поэтому изменение в одном месте немедленно видно в другом без ручной синхронизации.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эта архитектура станет буквальным шаблоном для будущей интеграции с backend (недели 21–22): внутри useTasks вызовы localStorage.setItem заменятся на fetch('/api/tasks', { method: 'POST' }), а интерфейс хука — { tasks, addTask, toggleTask, removeTask } — может остаться прежним. Компоненты, которые уже используют этот hook, не заметят разницы. Именно поэтому важно спроектировать интерфейс хука чисто уже сейчас, на учебном localStorage-варианте.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример иммутабельного обновления: toggleTask(id) должен делать setTasks(prev => prev.map(t => t.id === id ? { ...t, done: !t.done } : t)), а не искать задачу и менять task.done = true напрямую. Прямая мутация не только не вызовет ререндер сама по себе, но и незаметно «протухнет» производный state на Dashboard (день 93), который вычисляет статистику из этого же массива — на первый взгляд обновление вроде бы произошло (объект действительно изменился в памяти), но React не увидит новой ссылки и не перерисует использующие эти данные компоненты.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — относиться к key={index} как к безобидной формальности, лишь бы убрать warning в консоли. На самом деле при удалении задачи из середины списка все последующие элементы «сдвигают» свои индексы, и React из-за неправильного key может сопоставить старый DOM-узел не с той задачей — в лёгких случаях это просто визуальный глюк, а в более сложных, где TodoItem содержит <input> в режиме редактирования, это приводит к потере фокуса или к тому, что текст редактируется не в той строке, в которой видит пользователь. Стабильный key={task.id} из практики дня — не стилистическая рекомендация, а прямая защита от этого класса багов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: один useTasks на всё приложение; фильтры — derived state, не копия списка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Страница /tasks: форма добавления, список, фильтры (all/active/done)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Редактирование inline или modal
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Приоритет (цветовая метка) и дедлайн
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сортировка: по дате, приоритету
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Поиск по тексту задачи — filter + debounce
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. useTasks hook с persist в localStorage
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Подсветка просроченных задач (deadline < today)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] CRUD полностью работает, persist в localStorage

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Фильтры не ломают редактирование

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] key стабильный (id), не index

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Страница /tasks: форма добавления, список, фильтры (all/active/done)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Редактирование inline или modal
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Приоритет (цветовая метка) и дедлайн
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сортировка: по дате, приоритету
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-14\n\ngit add src/hooks/useTasks.ts src/pages/Tasks.tsx\n\ngit commit -m "week-14 day-94: useTasks, CRUD и фильтры"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          key={index} при удалении — скачки фокуса и баги

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Дублирование логики tasks в Dashboard и Tasks page

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 95 (Чт): Weather — интеграция внешнего API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Интеграция внешнего API — переход от учебного localStorage к реальному асинхронному миру. OpenWeather Current Weather API принимает город и ключ, возвращает температуру, влажность, описание и код иконки. Единицы (metric / imperial) лучше брать из Settings, а не хардкодить.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Три UI-состояния обязательны: loading (skeleton или spinner), error (сообщение + retry), success (данные). Проверяй res.ok — 401 (битый ключ), 404 (город не найден) и 429 (лимит free tier) должны давать понятный текст, а не «белый экран смерти». Кэш в sessionStorage на 10 минут с timestamp экономит квоту API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        useFetch или dedicated weatherApi.ts изолируют HTTP от компонента. Мини-виджет на Dashboard и полная страница /weather должны использовать один hook — иначе дублируется логика кэша. Debounce или submit по кнопке: запрос на каждый keystroke в поле города быстро исчерпает лимит.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель API-слоя: weatherApi.ts — это граница, за которой прячутся все детали конкретного сервиса (URL, ключ, формат ответа), а компонент Weather вообще не должен знать, что источник данных — именно OpenWeather, а не какой-то другой провайдер. Если завтра понадобится сменить сервис погоды, меняется только этот файл — UI и hook, которые его используют, остаются нетронутыми.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это разделение — не абстрактная архитектурная гигиена, а буквально тот же принцип, который появится на неделях 21–22 при подключении собственного backend: компонент вызывает getWeather(city), не зная и не заботясь о том, идёт ли запрос к внешнему API, к своему серверу или пока вообще к моковым данным. Правильно спроектированный weatherApi.ts сегодня — это репетиция будущего apiClient.ts для своих же REST-эндпоинтов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример квоты: free tier OpenWeather ограничен по количеству запросов в минуту/день. Кэш в sessionStorage с timestamp («если последний ответ для этого города младше 10 минут — используй его, не делай новый запрос») экономит квоту при обычном использовании (повторные заходы на страницу, переключение вкладок) и параллельно ускоряет восприятие — данные появляются мгновенно из кэша, а не после сетевого round-trip.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать, что fetch сам «выбросит ошибку» при неудачном HTTP-ответе, как это делает, например, axios по умолчанию. На самом деле fetch реджектит промис только при сетевом сбое (нет соединения, DNS не резолвится); ответ с кодом 401 (неверный ключ) или 404 (город не найден) — это полностью «успешный» с точки зрения fetch промис, просто с res.ok === false. Если не проверять res.ok явно и не бросать собственную ошибку, res.json() на теле ошибки OpenWeather ({ cod: 401, message: 'Invalid API key' }) отработает без исключений, и приложение попытается отрисовать погоду из объекта, где температуры попросту нет — это и есть тот самый «белый экран смерти», упомянутый в «Ловушках» дня, и практика явно требует обрабатывать 401/404/429 текстом, понятным пользователю, а не давать приложению упасть в неопределённое состояние.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: API-слой отдельно от UI; loading/error/success — на каждом экране с данными.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Страница /weather: input города, кнопка поиска
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Отображение: температура, описание, иконка, влажность, ветер
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Сохрани последний город в localStorage
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Обработка неверного API key и лимита запросов
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Кэш ответа в sessionStorage с timestamp
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Мини-виджет погоды на Dashboard (тот же hook)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Retry кнопка при сетевой ошибке
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Loading / error / success states

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Кэш 10 мин — повторный запрос не уходит в сеть

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Город по умолчанию из Settings

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Страница /weather: input города, кнопка поиска
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Отображение: температура, описание, иконка, влажность, ветер
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Сохрани последний город в localStorage
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Обработка неверного API key и лимита запросов
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-14\n\ngit add src/pages/Weather.tsx src/services/weatherApi.ts\n\ngit commit -m "week-14 day-95: OpenWeather API и кэш"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Запрос на каждый keystroke — debounce или submit по кнопке

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Не обработанный res.ok === false — «белый экран смерти»

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 96 (Пт): Settings — Context и персонализация

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Settings — центр персонализации и хороший тест на Context. Разделяй ThemeContext и UserContext: смена имени пользователя не должна перерисовывать подписчиков темы. Controlled form синхронизирует поля с state; изменения сразу отражаются на Dashboard и Weather без перезагрузки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        useId() генерирует стабильные id для связки label + input — важно для доступности и для избежания коллизий при нескольких формах. Валидация на клиенте (имя ≥ 2 символов, город не пустой) улучшает UX, даже если позже добавишь серверную проверку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Деструктивные действия («Сбросить настройки») требуют confirm dialog. Persist через localStorage в Provider или custom hook. Бонус export/import JSON — учит сериализовать state целиком. Toast при успешном сохранении даёт обратную связь без блокировки UI.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель Settings — это панель управления с несколькими независимыми переключателями, каждый из которых пишет в свой собственный Context, а не в один общий объект настроек. Это прямое практическое испытание урока с недели 13 (день 88): если разделение ThemeContext и UserContext было сделано правильно, ввод имени в форме настроек физически не должен вызывать перерисовку компонентов, подписанных только на тему — это легко проверить, поставив console.log('theme render') внутри компонента-потребителя ThemeContext и понаблюдав, срабатывает ли он при вводе имени.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Такая дисциплина разделения ответственности пригодится в любом реальном приложении с профилем и настройками пользователя — от простого лендинга с личным кабинетом до крупных SaaS-продуктов, где страница настроек — один из самых часто посещаемых и при этом самых «тяжёлых по side effects» экранов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример независимого persist: смена темы должна сохраняться в localStorage сразу при клике на переключатель (через useEffect внутри ThemeProvider), а смена имени пользователя — при submit формы, а не посимвольно при каждом нажатии клавиши. Смешение этих двух момента persist (когда именно писать в storage) — частый источник лишних записей на диск или, наоборот, потери данных при случайном закрытии вкладки до отправки формы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что раз useLocalStorage уже был написан на неделе 13, «persist происходит сам по себе» для любых новых данных без дополнительных действий. На самом деле каждый новый кусок state (единицы измерения °C/°F, город по умолчанию) требует либо использования того же useLocalStorage хука явно, либо ручного useEffect, который синхронизирует именно это значение — забытый шаг здесь означает, что настройка «применится сейчас», но пропадёт после F5, что напрямую противоречит критерию дня «настройки переживают перезагрузку». Кнопка «Сбросить настройки» без confirm() — ещё один риск: пользователь может случайно потерять персонализацию одним кликом, поэтому диалог подтверждения — не формальность, а обязательная защита от необратимого действия.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: Settings — single source для темы, города и единиц; разделяй контексты по доменам.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. /settings: имя, город по умолчанию, переключатель темы, единицы °C/°F
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Изменения сразу отражаются на Dashboard и Weather
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Кнопка «Сбросить настройки» с confirm dialog
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Экспорт/импорт настроек JSON (bonus)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. useId() для всех полей формы
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Валидация с сообщениями под полями
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Toast при успешном сохранении
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тема применяется ко всему приложению

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Настройки переживают F5

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Form labels связаны с inputs

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. /settings: имя, город по умолчанию, переключатель темы, единицы °C/°F
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Изменения сразу отражаются на Dashboard и Weather
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Кнопка «Сбросить настройки» с confirm dialog
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Экспорт/импорт настроек JSON (bonus)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-14\n\ngit add src/contexts/ src/pages/Settings.tsx\n\ngit commit -m "week-14 day-96: Settings, Context и персонализация"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Один Context на theme + user + settings — лишние ререндеры

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Сброс без confirm — случайная потеря данных

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 97 (Сб): Полировка UX и адаптив

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Полировка UX отличает «работает» от «приятно пользоваться». Адаптив — не опция: начни с 320px ширины, убедись, что нет horizontal scroll. Hamburger-меню на мобиле превращает sidebar в drawer; на desktop — постоянная навигация. Touch targets ≥ 44px снижают mis-tap на телефоне.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Доступность: :focus-visible вместо outline: none, tab-навигация по всем интерактивным элементам, контраст текста ≥ WCAG AA (проверь в DevTools). prefers-reduced-motion уважает настройки ОС — отключи лишние анимации для пользователей с вестибулярными расстройствами.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Toast-уведомления — лёгкий паттерн feedback при CRUD. Empty states («Нет задач — добавьте первую») лучше пустой таблицы. Lighthouse audit: цель Performance ≥ 80, Accessibility ≥ 90. Микро-анимации через CSS transitions добавляют «живости» без тяжёлых библиотек.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель этого дня: «Definition of Done» для интерфейса включает доступность и мобильную адаптацию по умолчанию, а не как опциональный бонус «если останется время». Полезная привычка — проектировать от 320px вверх (mobile-first), а не тестировать desktop-версию и потом «сжимать» её медиа-запросами: вторая стратегия почти всегда приводит к горизонтальному скроллу и мелкому тексту на реальных телефонах.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это напрямую влияет на оценку проекта в реальном мире: Lighthouse Accessibility и Performance — метрики, которые смотрят рекрутеры и тимлиды при код-ревью портфолио, а в некоторых юрисдикциях доступность интерфейса — не пожелание, а юридическое требование (WCAG). Мобильный трафик во многих продуктах составляет больше половины пользователей, так что «доделать адаптив потом» на практике означает «сломанный опыт для большинства».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: outline: none на кнопке без замены полностью убирает визуальную индикацию фокуса — пользователь, управляющий сайтом только клавиатурой (Tab), физически не видит, на каком элементе находится. :focus-visible — правильная замена: она показывает обводку при навигации с клавиатуры, но не мешает эстетике при клике мышью, где фокус менее важен визуально.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — тестировать интерфейс только на своём ноутбуке с мышью и считать «выглядит нормально» достаточным критерием готовности. Это никак не проверяет tab-навигацию, touch-target размеры (кнопка 24×24px удобна для курсора, но промахивается пальцем), контраст текста при ярком солнечном свете или вестибулярную нагрузку от резких анимаций у части пользователей — отсюда обязательность prefers-reduced-motion. Практика дня требует явной проверки на 320px и через Lighthouse именно потому, что визуальная проверка «на глаз» систематически пропускает эти категории проблем — это касается и мобильного меню (hamburger → drawer), которое должно быть доступно и с клавиатуры, не только тапом по иконке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: a11y и mobile-first — часть Definition of Done, не «потом».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Мобильное меню (hamburger → drawer)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Toast-уведомления: задача добавлена, ошибка API
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Empty state: «Нет задач — добавьте первую»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Lighthouse audit — цель Performance ≥ 80, Accessibility ≥ 90
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Focus styles на всех интерактивных элементах
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Проверка на 320px ширине — нет horizontal scroll
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. CSS transitions на hover/focus (с reduced-motion fallback)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Tab-навигация по всем интерактивным элементам

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет горизонтального скролла на 320px

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Lighthouse Accessibility ≥ 90

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Мобильное меню (hamburger → drawer)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Toast-уведомления: задача добавлена, ошибка API
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Empty state: «Нет задач — добавьте первую»
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Lighthouse audit — цель Performance ≥ 80, Accessibility ≥ 90
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-14\n\ngit add src/components/\n\ngit commit -m "week-14 day-97: mobile nav, toast и a11y polish"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          outline: none без замены — ломает a11y

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Фиксированная sidebar на мобиле закрывает контент

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 98 (Вс): Тестирование вручную и документация

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к React Dashboard

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        React Dashboard — крупнейший фронтенд-проект до бэкенда; день ревью фиксирует качество, а не добавляет фичи. Пройди user flow глазами новичка: первый визит → настройки → задачи → погода → смена темы → F5. Каждый шаг должен работать без инструкции в README.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Production build (npm run build) часто выявляет warnings, которые dev-сервер скрывает: неиспользуемые импорты, env без fallback. Deploy на Vercel/Netlify требует настройки SPA fallback для client-side routes. README с GIF или скриншотами — визитная карточка для портфолио.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Conventional Commits за неделю показывают зрелость: feat:, fix:, docs: в сообщениях. ARCHITECTURE.md обнови финальной схемой state. Этот проект станет основой для full-stack интеграции на неделях 21–22 — чистая структура сейчас сэкономит часы потом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель дня ревью: посмотри на свой проект глазами человека, который видит его первый раз и не читал твой код — именно так его увидит рекрутер, тимлид на код-ревью или случайный посетитель портфолио. User flow «первый визит → настройки → задачи → погода → смена темы → F5» — это ручной аналог QA-сценария (test case), который проверяет не отдельные функции, а связность всего приложения как единого продукта.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Привычка проверять npm run build перед тем, как считать день/неделю законченными, — то, что отличает учебный проект от production-ready: dev-сервер Vite нередко прощает вещи, которые ломаются в собранном бандле — например, переменную окружения без fallback-значения, которая в dev была подставлена из .env, а в проде на Vercel забыли настроить, и приложение падает в рантайме с непонятной ошибкой вместо явного сообщения при сборке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример скрытой проблемы: неиспользуемый импорт компонента, случайно оставленный после рефакторинга, в dev-режиме никак не мешает работе, но при npm run build в strict-конфигурации может всплыть предупреждением, а в некоторых сетапах — и ошибкой, останавливающей деплой; лучше поймать это самому за 5 минут локально, чем через уведомление о падении билда на хостинге.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — недооценивать README, считая его формальностью «для галочки». На практике именно README — первое, что видит любой человек, открывший репозиторий (рекрутер за 30 секунд решает, смотреть ли код дальше), и единственный способ показать масштаб проделанной работы без необходимости запускать проект локально. GIF или три скриншота стоят десятков строк текстового описания фичей. Это же качество документации станет частью финального full-stack проекта на неделях 21–22, где React Dashboard, разработанный на этой неделе, получит настоящий backend — и осмысленная git-история с Conventional Commits, начатая уже сейчас, сделает эту интеграцию прослеживаемой, а не хаотичной.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: capstone-качество начинается с README, deploy preview и осмысленной git-истории.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди user flow: первый визит → настройки → задачи → погода → смена темы → F5
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Напиши README с GIF или 3 скриншотами
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. npm run build — исправь warnings
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Deploy preview на Vercel
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Обнови ARCHITECTURE.md — финальная схема state
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Self-review по ревью-чеклисту недели
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-14-done
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Production build без ошибок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] README понятен новичку

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Preview URL в README

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди user flow: первый визит → настройки → задачи → погода → смена темы → F5
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Напиши README с GIF или 3 скриншотами
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. npm run build — исправь warnings
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Deploy preview на Vercel
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-14\n\ngit add README.md ARCHITECTURE.md\n\ngit commit -m "week-14 day-98: README, deploy и React Dashboard capstone"\n\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        React Dashboard SPA — итоговый deliverable недели, крупнейший фронтенд-проект до бэкенда. Подробное ТЗ: docs/projects.md — Неделя 14.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Маршруты: / статистика, /tasks CRUD, /weather API, /settings тема и user. React Router, hooks, Context, адаптив, deploy preview.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Dashboard с live-статистикой из tasks и user context

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Tasks: CRUD, приоритет, дедлайн, фильтры, поиск

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Weather: OpenWeatherMap, кэш, retry, единицы из settings

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Settings: тема, имя, город, export/import (bonus)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Все 4 страницы полностью функциональны

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Нет prop drilling глубже 2 уровней

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] GitHub repo с понятной историей коммитов (≥ 7 за неделю)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Vercel/Netlify preview работает

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Lighthouse Accessibility ≥ 90

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] .env.example без реальных ключей

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тег week-14-done

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Могу объяснить архитектуру проекта за 2 минуты?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Где хранится state задач и почему именно там?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Как бы добавил авторизацию к этому Dashboard?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Что произойдёт при истечении API-ключа OpenWeather?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Какие 3 улучшения сделал бы в v2?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **React Dashboard** в `learning-log/week-14/`, осмысленная Git-история, тег `week-14-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nПолноценное frontend SPA\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-14-day-92", "label": "День 92 (Пн): Архитектура и скелет проекта"}, {"id": "week-14-day-93", "label": "День 93 (Вт): Dashboard — статистика и карточки"}, {"id": "week-14-day-94", "label": "День 94 (Ср): Tasks — CRUD и фильтрация"}, {"id": "week-14-day-95", "label": "День 95 (Чт): Weather — интеграция внешнего API"}, {"id": "week-14-day-96", "label": "День 96 (Пт): Settings — Context и персонализация"}, {"id": "week-14-day-97", "label": "День 97 (Сб): Полировка UX и адаптив"}, {"id": "week-14-day-98", "label": "День 98 (Вс): Тестирование вручную и документация"}, {"id": "week-14-project", "label": "Проект недели"}, {"id": "week-14-review", "label": "Ревью-чеклист"}], "text": "Неделя 14: Frontend Capstone — React Dashboard Цель недели: собрать полноценное SPA-приложение, объединяющее все навыки React-фронтенда. Литература: react.dev , React Router , OpenWeatherMap API , Vite Env Variables , web.dev — Web Vitals Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-14/ День 92 (Пн): Архитектура и скелет проекта Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к React Dashboard Теория Frontend capstone начинается с архитектуры, а не с кода. Прежде чем писать компоненты, зафиксируй страницы ( / , /tasks , /weather , /settings ), источники данных (localStorage, Context, внешний API) и границы ответственности модулей. Хоро…"} \ No newline at end of file diff --git a/docs/weeks/15.json b/docs/weeks/15.json index 565daa8..b3b6464 100644 --- a/docs/weeks/15.json +++ b/docs/weeks/15.json @@ -1 +1 @@ -{"id": "week-15", "title": "Python", "fullTitle": "Неделя 15: Python — основы", "html": "

                                                                                                                                                                                                                        Неделя 15: Python — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: освоить синтаксис Python, структуры данных, функции и изолированное окружение.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература: Python Tutorial, Real Python, «Python. Ускоренный курс» (Теллез), PEP 8, Python venv

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git: минимум 1 осмысленный коммит каждый день в learning-log/week-15/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 99 (Пн): Установка, синтаксис, venv

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Expense Tracker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Python — первый шаг в backend после фронтенда. Установка с python.org (или py launcher на Windows) и проверка python --version — база. Главная привычка с первого дня: виртуальное окружение python -m venv .venv изолирует зависимости проекта от системного Python. Без активации venv пакеты ставятся глобально и ломают другие проекты.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Синтаксис Python читается почти как псевдокод: отступы (4 пробела, PEP 8) — часть языка, не стиль. Типы: int, float, str, bool, None. f-strings (f\"Привет, {name}\") — современный способ форматирования. input() всегда возвращает строку — для чисел нужен int() или float() с обработкой ValueError.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Операторы // (целочисленное деление) и % (остаток) пригодятся в задачах. REPL (python без аргументов) — быстрая проверка выражений. python -m pip install ставит пакеты в активный venv. Shebang #!/usr/bin/env python3 полезен для скриптов на Unix, на Windows — вторично.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: venv на каждый проект; input() — всегда str, отступы — синтаксис.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Установи Python 3.11+, проверь python --version
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Создай проект learning-log/week-15, venv, pip install --upgrade pip
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. hello.py — приветствие по имени из input()
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. calculator.py — меню: +, -, *, /, выход
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. .gitignore с .venv/ и __pycache__/
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Обработка ValueError при неверном вводе числа
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. README.md с инструкцией активации venv
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] venv активирован, зависимости не в global Python

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] requirements.txt пустой или с комментарием (пока без пакетов)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Обработка деления на ноль

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Установи Python 3.11+, проверь python --version
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Создай проект learning-log/week-15, venv, pip install --upgrade pip
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. hello.py — приветствие по имени из input()
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. calculator.py — меню: +, -, *, /, выход
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-15\n\ngit add hello.py calculator.py .gitignore README.md\n\ngit commit -m "week-15 day-99: venv, hello.py и calculator"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Забытая активация venv — пакеты ставятся глобально

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          input() всегда возвращает str — нужен int() / float()

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 100 (Вт): Условия, циклы, comprehensions

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~30м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Expense Tracker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Условия и циклы — скелет любой программы. if/elif/else опирается на truthiness: пустой список [], строка \"\", ноль 0 и None — falsy. Это отличается от JavaScript, где только некоторые значения falsy. Циклы for итерируют по итерируемым объектам; while — пока условие истинно; break и continue управляют потоком.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        range(n) генерирует последовательность без создания списка в памяти. enumerate(items) даёт пары (индекс, элемент) — идиоматичнее, чем for i in range(len(items)). zip(a, b) объединяет два списка попарно. У цикла for есть необязательный else, выполняющийся, если не было break — редкий, но полезный приём.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        List comprehension [x**2 for x in range(10) if x % 2 == 0] компактно строит список. Не увлекайся вложенностью — читаемость важнее одной строки. Walrus := (3.8+) присваивает в выражении. Не изменяй список во время итерации по нему — пропустишь элементы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: comprehension — сахар над циклом; is vs == — разные вещи для объектов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. FizzBuzz 1–100
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Таблица умножения 10×10 через nested loops
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Список квадратов чётных чисел 0–20 через comprehension
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Игра «Угадай число» с ограничением попыток
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. fizzbuzz.py с функцией fizzbuzz(n) -> list[str]
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Dict comprehension: {x: x**2 for x in range(10)}
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Подсчёт гласных в строке через for и in
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] FizzBuzz выводит корректно

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Хотя бы 2 задачи через comprehension

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] while с условием выхода, не while True без break

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. FizzBuzz 1–100
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Таблица умножения 10×10 через nested loops
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Список квадратов чётных чисел 0–20 через comprehension
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Игра «Угадай число» с ограничением попыток
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-15\n\ngit add fizzbuzz.py exercises/\n\ngit commit -m "week-15 day-100: FizzBuzz, циклы и comprehensions"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Изменение списка во время итерации по нему — пропуск элементов

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          is vs == для сравнения строк и чисел

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 101 (Ср): Функции и type hints

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Expense Tracker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции в Python — первый уровень абстракции. def name(args) -> return_type: с type hints документирует контракт для IDE и будущего mypy. Docstring в тройных кавычках (PEP 257) объясняет назначение, аргументы и возвращаемое значение. if __name__ == \"__main__\": отделяет точку входа от импортируемого модуля.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Аргументы по умолчанию должны быть immutable: def f(x=[]) — антипаттерн, один список на все вызовы. Используй None и создавай список внутри. *args собирает позиционные аргументы, **kwargs — именованные. После * в сигнатуре — только keyword-only аргументы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Чистые функции (без side effects) проще тестировать: celsius_to_fahrenheit(0) всегда даёт 32.0. Функция без return неявно возвращает None — частая ловушка. Scope: избегай global, передавай данные аргументами.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: mutable default argument — баг; type hints и docstrings — часть API функции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Модуль utils.py: celsius_to_fahrenheit, format_currency, truncate_text
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CLI-конвертер валют (фиксированные курсы в dict)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь type hints и docstrings ко всем функциям
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. if __name__ == \"__main__\": — точка входа
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Функция parse_positive_float(s: str) -> float с валидацией
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. *args demo: sum_all(*numbers)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Импорт utils из другого файла — проверь, main не запускается
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Функции чистые где возможно (без side effects)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Type hints на аргументах и return

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Модуль импортируется без запуска main-логики

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Модуль utils.py: celsius_to_fahrenheit, format_currency, truncate_text
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CLI-конвертер валют (фиксированные курсы в dict)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь type hints и docstrings ко всем функциям
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. if __name__ == \"__main__\": — точка входа
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-15\n\ngit add utils.py currency_converter.py\n\ngit commit -m "week-15 day-101: функции, type hints и utils"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Mutable default argument def f(x=[]) — общий список на все вызовы

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Функция без return → None неожиданно

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 102 (Чт): Структуры данных — list, tuple, dict, set

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Expense Tracker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Выбор структуры данных определяет скорость и читаемость кода. list — упорядоченная изменяемая коллекция: append, extend, срезы lst[1:3], сортировка in-place (sort) или новый список (sorted). dict — словарь по hashable-ключам: lookup в среднем O(1) против O(n) у списка. .get(key, default) безопаснее прямого dict[key].

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        set хранит уникальные элементы и поддерживает union, intersection, difference — удобно для удаления дубликатов. tuple неизменяем: подходит для координат, записей из БД, ключей словаря. collections.Counter ускоряет подсчёт частот. Копирование: copy.copy — shallow, copy.deepcopy — вложенные структуры.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Телефонная книга на dict[name] = phone — классический CRUD. Список нельзя использовать как ключ dict (unhashable). Для сортировки списка словарей: sorted(items, key=lambda x: x['score']).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: dict для поиска по ключу, list для порядка; выбор структуры — это Big-O.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Телефонная книга: dict[name] = phone, CRUD через меню
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Подсчёт частоты слов в тексте через dict
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Удаление дубликатов из списка через set, сохраняя порядок (bonus)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сортировка списка словарей по ключу score
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. phonebook.py — функции add, remove, search, list_all
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Поиск по частичному совпадению имени
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Валидация формата телефона (простой regex или len)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Телефонная книга persist в JSON-файл

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] .get() вместо KeyError для отсутствующих ключей

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Понимаешь O(1) lookup в dict vs O(n) в list

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Телефонная книга: dict[name] = phone, CRUD через меню
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Подсчёт частоты слов в тексте через dict
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Удаление дубликатов из списка через set, сохраняя порядок (bonus)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сортировка списка словарей по ключу score
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-15\n\ngit add phonebook.py\n\ngit commit -m "week-15 day-102: телефонная книга и структуры данных"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Использование list как ключа dict — TypeError (unhashable)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          list.sort() vs sorted(list) — in-place vs новый список

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 103 (Пт): Работа с файлами и JSON

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Expense Tracker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Файлы и JSON — мост между программой и диском. Context manager with open(path, 'r', encoding='utf-8') as f: гарантирует закрытие файла даже при исключении. На Windows encoding='utf-8' критичен для кириллицы. Режимы: r чтение, w перезапись, a дополнение в конец.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Модуль json: load/dump для файлов, loads/dumps для строк. ensure_ascii=False сохраняет Unicode, indent=2 делает файл читаемым для человека. Обрабатывай FileNotFoundError (первый запуск) и JSONDecodeError (битый файл) — graceful start важнее краша.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        pathlib.Path — современная альтернатива строковым путям: Path('data') / 'contacts.json'. Atomic write (запись во временный файл + rename) защищает от потери данных при сбое. Для отладки — print, для production — модуль logging с уровнями.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: всегда with open и encoding='utf-8'; JSON — контракт persist между запусками.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Расширь телефонную книгу: save/load contacts.json
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Логгер: append строки в app.log с timestamp
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Чтение CSV вручную (split по запятой) → list of dicts
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Backup: копия JSON перед перезаписью
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. storage.py — функции load_contacts(), save_contacts(data)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Graceful start если contacts.json не существует
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Импорт контактов из CSV файла
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Все файлы через with open

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] ensure_ascii=False для кириллицы в JSON

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Graceful handling если файл не существует

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Расширь телефонную книгу: save/load contacts.json
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Логгер: append строки в app.log с timestamp
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Чтение CSV вручную (split по запятой) → list of dicts
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Backup: копия JSON перед перезаписью
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-15\n\ngit add storage.py data/\n\ngit commit -m "week-15 day-103: JSON persist, логгер и CSV import"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Забытый encoding='utf-8' на Windows — кракозябры

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          json.dump без indent — нечитаемый файл для человека

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 104 (Сб): Модули, пакеты, pip

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Expense Tracker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Модули и пакеты масштабируют код за пределы одного файла. import module и from package import name — два стиля; второй удобнее, но может засорить namespace. Пакет — папка с __init__.py (в Python 3.3+ namespace packages возможны без него, но для учебных проектов __init__.py явно). __all__ объявляет публичный API пакета.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        pip install package ставит зависимости в venv; pip freeze > requirements.txt фиксирует версии для воспроизводимых сборок. Pin versions (rich==13.x.x) защищает от неожиданных breaking changes. PyPI — реестр пакетов: requests, rich и тысячи других.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Запуск python -m phonebook.cli выполняет модуль как скрипт с корректными относительными импортами. Избегай циклических импортов: models не должен импортировать cli. Не называй файл json.py — затенишь стандартный модуль.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: пакетная структура + requirements.txt — основа любого Python-проекта.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Разбей телефонную книгу: models.py, storage.py, cli.py
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. pip install rich — красивый вывод таблицы контактов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. requirements.txt с rich==...
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Запуск: python -m phonebook.cli
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Пакет phonebook/ с __init__.py
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Rich Table для list contacts с колонками name, phone
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Цветной вывод ошибок через rich.print
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Пакетная структура с __init__.py

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] requirements.txt актуален

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] rich Table для list contacts

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Разбей телефонную книгу: models.py, storage.py, cli.py
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. pip install rich — красивый вывод таблицы контактов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. requirements.txt с rich==...
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Запуск: python -m phonebook.cli
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-15\n\ngit add phonebook/ requirements.txt\n\ngit commit -m "week-15 day-104: пакет phonebook и rich CLI"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Циклические импорты — раздели слои (models не импортирует cli)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Имя файла json.py — затеняет стандартный модуль

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 105 (Вс): Ревью основ Python

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Expense Tracker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью недели закрепляет фундамент перед CLI Expense Tracker. PEP 8 — не догма, а общий язык: snake_case для функций и переменных, 79–88 символов в строке, два пустых ряда между top-level определениями. python -m py_compile file.py проверяет синтаксис без запуска.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Сравни Python с JavaScript: отступы вместо {}, None вместо null, иная truthiness, явный self в методах. HackerRank/Codewars на Easy уровне тренируют синтаксис вне контекста проекта. Шпаргалка list vs tuple vs dict vs set — шпаргалка на всю карьеру.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CLI Expense Tracker объединяет всё: venv, модули, JSON persist, rich для таблиц, валидацию ввода. README с примерами команд — обязателен. Осмысленные коммиты за 7 дней и тег week-15-done завершают неделю.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: Python-проект = venv + модули + persist + README; стиль PEP 8 с первого коммита.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реши 10 задач на HackerRank Python (Easy)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рефакторинг телефонной книги по PEP 8
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Напиши шпаргалку: list vs tuple vs dict vs set
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Начни скелет CLI Expense Trackerexpense_tracker/
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. notes/python-structures.md — шпаргалка структур
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Прогони python -m py_compile на всех модулях
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-15-done
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] 10 задач HackerRank решены

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Код проходит python -m py_compile без ошибок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Шпаргалка в notes/python-structures.md

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реши 10 задач на HackerRank Python (Easy)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рефакторинг телефонной книги по PEP 8
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Напиши шпаргалку: list vs tuple vs dict vs set
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Начни скелет CLI Expense Trackerexpense_tracker/
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-15\n\ngit add notes/ expense_tracker/\n\ngit commit -m "week-15 day-105: HackerRank, PEP 8 и Expense Tracker скелет"\n\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CLI Expense Tracker — трекер расходов в терминале. Подробное ТЗ: docs/projects.md — Неделя 15.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. \n

                                                                                                                                                                                                                          Категории: food, transport, entertainment, other

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. \n

                                                                                                                                                                                                                          Добавление, список, удаление, сумма по категории, общий итог

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. \n

                                                                                                                                                                                                                          Хранение в expenses.json

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. \n

                                                                                                                                                                                                                          rich — таблица и цветной вывод

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. \n

                                                                                                                                                                                                                          Фильтр по дате (строка YYYY-MM-DD)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          CLI-меню или subcommands: add, list, delete, summary, filter

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Валидация суммы (> 0) и формата даты

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Сводка по категориям с итогами

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Цветной вывод: доход зелёный, расход красный (опционально)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] venv + requirements.txt с pinned versions

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Модульная структура (≥ 3 файла: models, storage, cli)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Валидация суммы (> 0) и даты

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] README с примерами команд

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] rich Table для списка расходов

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Persist в JSON, переживает перезапуск

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тег week-15-done

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Зачем venv и чем отличается от global Python?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          list vs tuple — когда использовать каждый?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Что такое list comprehension и зачем?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Как работает with open()?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Чем == отличается от is?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **CLI Expense Tracker** в `learning-log/week-15/`, осмысленная Git-история, тег `week-15-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nPython основы и CLI\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-15-day-99", "label": "День 99 (Пн): Установка, синтаксис, venv"}, {"id": "week-15-day-100", "label": "День 100 (Вт): Условия, циклы, comprehensions"}, {"id": "week-15-day-101", "label": "День 101 (Ср): Функции и type hints"}, {"id": "week-15-day-102", "label": "День 102 (Чт): Структуры данных — list, tuple, dict, set"}, {"id": "week-15-day-103", "label": "День 103 (Пт): Работа с файлами и JSON"}, {"id": "week-15-day-104", "label": "День 104 (Сб): Модули, пакеты, pip"}, {"id": "week-15-day-105", "label": "День 105 (Вс): Ревью основ Python"}, {"id": "week-15-project", "label": "Проект недели"}, {"id": "week-15-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-15-review", "label": "Проверь себя"}], "text": "Неделя 15: Python — основы Цель недели: освоить синтаксис Python, структуры данных, функции и изолированное окружение. Литература: Python Tutorial , Real Python , «Python. Ускоренный курс» (Теллез), PEP 8 , Python venv Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-15/ День 99 (Пн): Установка, синтаксис, venv Время (полный): ~1ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к CLI Expense Tracker Теория Python — первый шаг в backend после фронтенда. Установка с python.org (или py launcher на Windows) и проверка python --version — база. Главная привычка с первого дня: виртуальное окружение python -m venv .venv изолирует зависимости проекта от системного Pyt…"} \ No newline at end of file +{"id": "week-15", "title": "Python", "fullTitle": "Неделя 15: Python — основы", "html": "

                                                                                                                                                                                                                        Неделя 15: Python — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: освоить синтаксис Python, структуры данных, функции и изолированное окружение.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Литература: Python Tutorial, Real Python, «Python. Ускоренный курс» (Теллез), PEP 8, Python venv

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели: см. docs/projects.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git: минимум 1 осмысленный коммит каждый день в learning-log/week-15/

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 99 (Пн): Установка, синтаксис, venv

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Expense Tracker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Python — первый шаг в backend после фронтенда. Установка с python.org (или py launcher на Windows) и проверка python --version — база. Главная привычка с первого дня: виртуальное окружение python -m venv .venv изолирует зависимости проекта от системного Python. Без активации venv пакеты ставятся глобально и ломают другие проекты.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Синтаксис Python читается почти как псевдокод: отступы (4 пробела, PEP 8) — часть языка, не стиль. Типы: int, float, str, bool, None. f-strings (f\"Привет, {name}\") — современный способ форматирования. input() всегда возвращает строку — для чисел нужен int() или float() с обработкой ValueError.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Операторы // (целочисленное деление) и % (остаток) пригодятся в задачах. REPL (python без аргументов) — быстрая проверка выражений. python -m pip install ставит пакеты в активный venv. Shebang #!/usr/bin/env python3 полезен для скриптов на Unix, на Windows — вторично.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель venv: это то же самое, что node_modules в мире Node.js, но для Python нужно создавать его явно, потому что интерпретатор по умолчанию один на всю систему, а не «per project», как в JS-экосистеме с локальными зависимостями из коробки. python -m venv .venv создаёт изолированную копию интерпретатора и пространство для пакетов именно этого проекта — активация переключает python и pip на эту копию, деактивация возвращает к системной версии.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Привычка, сформированная сегодня, будет использоваться в каждом Python-проекте до конца курса: без venv два учебных проекта, которым нужны разные версии одной библиотеки, начнут конфликтовать в системном Python, а на реальной работе разные сервисы одной компании почти гарантированно требуют разных версий одних и тех же зависимостей.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример конфликта: проект A на неделе 15 использует rich==13.0, а гипотетический проект B — rich==14.0 с другим API. Без venv установка пакета для проекта B перезапишет глобальную версию и сломает проект A при следующем запуске — оба будут молча использовать не ту версию библиотеки, для которой писался код.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать, что установка «всего одного пакета» без активного venv не страшна, потому что «он маленький» или «я потом уберу». На практике такие исключения накапливаются: через несколько недель системный Python оказывается захламлён десятками пакетов из разных мини-экспериментов, версии конфликтуют между собой, а диагностировать, какой пакет откуда взялся, почти невозможно. Именно поэтому в критериях дня явно указано «venv активирован, зависимости не в global Python» — это не бюрократическая формальность, а страховка от часов будущей отладки при работе над hello.py и calculator.py, где пока используются только встроенные возможности языка, но привычка ставится с первого файла.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: venv на каждый проект; input() — всегда str, отступы — синтаксис.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Установи Python 3.11+, проверь python --version
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Создай проект learning-log/week-15, venv, pip install --upgrade pip
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. hello.py — приветствие по имени из input()
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. calculator.py — меню: +, -, *, /, выход
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. .gitignore с .venv/ и __pycache__/
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Обработка ValueError при неверном вводе числа
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. README.md с инструкцией активации venv
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] venv активирован, зависимости не в global Python

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] requirements.txt пустой или с комментарием (пока без пакетов)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Обработка деления на ноль

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Установи Python 3.11+, проверь python --version
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Создай проект learning-log/week-15, venv, pip install --upgrade pip
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. hello.py — приветствие по имени из input()
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. calculator.py — меню: +, -, *, /, выход
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-15\n\ngit add hello.py calculator.py .gitignore README.md\n\ngit commit -m "week-15 day-99: venv, hello.py и calculator"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Забытая активация venv — пакеты ставятся глобально

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          input() всегда возвращает str — нужен int() / float()

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 100 (Вт): Условия, циклы, comprehensions

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Expense Tracker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Условия и циклы — скелет любой программы. if/elif/else опирается на truthiness: пустой список [], строка \"\", ноль 0 и None — falsy. Это отличается от JavaScript, где только некоторые значения falsy. Циклы for итерируют по итерируемым объектам; while — пока условие истинно; break и continue управляют потоком.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        range(n) генерирует последовательность без создания списка в памяти. enumerate(items) даёт пары (индекс, элемент) — идиоматичнее, чем for i in range(len(items)). zip(a, b) объединяет два списка попарно. У цикла for есть необязательный else, выполняющийся, если не было break — редкий, но полезный приём.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        List comprehension [x**2 for x in range(10) if x % 2 == 0] компактно строит список. Не увлекайся вложенностью — читаемость важнее одной строки. Walrus := (3.8+) присваивает в выражении. Не изменяй список во время итерации по нему — пропустишь элементы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель list comprehension: это декларативное «что» вместо императивного «как». Обычный цикл for описывает пошаговый процесс («иди по каждому элементу, проверяй условие, добавляй в новый список»); comprehension [x**2 for x in range(10) if x % 2 == 0] описывает сразу результат — «список квадратов чётных чисел от 0 до 9» — и читается почти как математическая нотация множества. Это не просто короче — это другой способ мышления о трансформации данных, который окажется повсюду в реальном Python-коде: обработка данных, фильтрация запросов к БД в Django ORM использует концептуально похожий стиль.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Понимание truthiness критично именно потому, что ты уже знаком с JavaScript и подсознательно можешь перенести не те правила: в Python 0, 0.0, \"\", [], {}, None и False — falsy, всё остальное — truthy, и в этом Python на самом деле почти как JS. Но есть тонкость: в JS NaN тоже falsy, а в Python отдельного «falsy NaN» с таким поведением нет — сравнения устроены иначе, и полагаться на интуицию из JS без проверки документации рискованно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: проверка пустого списка задач if not tasks: — идиоматичный Python, эквивалентный по смыслу if (tasks.length === 0) в JS, но синтаксически основанный именно на truthiness пустой коллекции, а не на явном сравнении длины.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — писать if tasks == []: вместо if not tasks:, что технически работает, но не идиоматично и не сработает единообразно для других falsy-коллекций ({}, set()). Ещё одна ошибка, специфичная для новичков с опытом в JS, — изменять список прямо во время итерации по нему (for item in items: items.remove(item)), что в Python приводит к пропуску элементов из-за сдвига индексов внутри итератора, а не к очевидной ошибке — именно это явно указано в «Ловушках» дня и стоит проверить на практике при написании FizzBuzz и задач с comprehension.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: comprehension — сахар над циклом; is vs == — разные вещи для объектов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. FizzBuzz 1–100
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Таблица умножения 10×10 через nested loops
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Список квадратов чётных чисел 0–20 через comprehension
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Игра «Угадай число» с ограничением попыток
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. fizzbuzz.py с функцией fizzbuzz(n) -> list[str]
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Dict comprehension: {x: x**2 for x in range(10)}
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Подсчёт гласных в строке через for и in
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] FizzBuzz выводит корректно

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Хотя бы 2 задачи через comprehension

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] while с условием выхода, не while True без break

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. FizzBuzz 1–100
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Таблица умножения 10×10 через nested loops
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Список квадратов чётных чисел 0–20 через comprehension
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Игра «Угадай число» с ограничением попыток
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-15\n\ngit add fizzbuzz.py exercises/\n\ngit commit -m "week-15 day-100: FizzBuzz, циклы и comprehensions"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Изменение списка во время итерации по нему — пропуск элементов

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          is vs == для сравнения строк и чисел

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 101 (Ср): Функции и type hints

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Expense Tracker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции в Python — первый уровень абстракции. def name(args) -> return_type: с type hints документирует контракт для IDE и будущего mypy. Docstring в тройных кавычках (PEP 257) объясняет назначение, аргументы и возвращаемое значение. if __name__ == \"__main__\": отделяет точку входа от импортируемого модуля.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Аргументы по умолчанию должны быть immutable: def f(x=[]) — антипаттерн, один список на все вызовы. Используй None и создавай список внутри. *args собирает позиционные аргументы, **kwargs — именованные. После * в сигнатуре — только keyword-only аргументы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Чистые функции (без side effects) проще тестировать: celsius_to_fahrenheit(0) всегда даёт 32.0. Функция без return неявно возвращает None — частая ловушка. Scope: избегай global, передавай данные аргументами.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель функции с type hints: сигнатура — это контракт, который читают не только люди, но и инструменты. def celsius_to_fahrenheit(c: float) -> float: сообщает IDE, что автодополнение и подсказки типов работают для параметра и результата, а mypy может статически проверить, что функция нигде не вызывается с неверным типом — задолго до того, как ошибка проявится в рантайме. Docstring в тройных кавычках — та же идея для смысла: не «что делает код», а «что обещает функция», включая крайние случаи.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эта дисциплина станет строго необходимой позже: любой современный Python backend-фреймворк (FastAPI, с которым познакомишься в конце курса) строит валидацию запросов и автогенерацию документации API прямо на type hints — то есть привычка, выработанная сегодня на простых функциях вроде format_currency, напрямую превратится в рабочий навык для реальных веб-сервисов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример mutable default argument: def add_item(item, bag=[]): bag.append(item); return bag. Кажется, что каждый вызов получает свежий пустой список, но список [] в сигнатуре создаётся один раз, в момент определения функции, а не при каждом вызове — поэтому второй вызов add_item('apple') без явного bag вернёт список, в котором уже лежит результат первого вызова, что выглядит как необъяснимая утечка состояния между полностью независимыми вызовами функции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — переносить в Python интуицию из языков, где значение по умолчанию действительно вычисляется заново при каждом вызове функции; в Python дефолтное значение — это выражение, вычисленное ровно один раз при объявлении def, и если это изменяемый объект (список, словарь, множество), он становится общим для всех вызовов, где аргумент не передан явно. Правильный паттерн — def add_item(item, bag=None): bag = bag if bag is not None else [] — обсуждается прямо в «Ловушках» дня и должен быть применён при реализации utils.py и CLI-конвертера валют, где список курсов или история конвертаций легко могли бы попасть в эту же ловушку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: mutable default argument — баг; type hints и docstrings — часть API функции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Модуль utils.py: celsius_to_fahrenheit, format_currency, truncate_text
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CLI-конвертер валют (фиксированные курсы в dict)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь type hints и docstrings ко всем функциям
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. if __name__ == \"__main__\": — точка входа
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Функция parse_positive_float(s: str) -> float с валидацией
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. *args demo: sum_all(*numbers)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Импорт utils из другого файла — проверь, main не запускается
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Функции чистые где возможно (без side effects)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Type hints на аргументах и return

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Модуль импортируется без запуска main-логики

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Модуль utils.py: celsius_to_fahrenheit, format_currency, truncate_text
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CLI-конвертер валют (фиксированные курсы в dict)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Добавь type hints и docstrings ко всем функциям
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. if __name__ == \"__main__\": — точка входа
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-15\n\ngit add utils.py currency_converter.py\n\ngit commit -m "week-15 day-101: функции, type hints и utils"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Mutable default argument def f(x=[]) — общий список на все вызовы

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Функция без return → None неожиданно

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 102 (Чт): Структуры данных — list, tuple, dict, set

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Expense Tracker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Выбор структуры данных определяет скорость и читаемость кода. list — упорядоченная изменяемая коллекция: append, extend, срезы lst[1:3], сортировка in-place (sort) или новый список (sorted). dict — словарь по hashable-ключам: lookup в среднем O(1) против O(n) у списка. .get(key, default) безопаснее прямого dict[key].

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        set хранит уникальные элементы и поддерживает union, intersection, difference — удобно для удаления дубликатов. tuple неизменяем: подходит для координат, записей из БД, ключей словаря. collections.Counter ускоряет подсчёт частот. Копирование: copy.copy — shallow, copy.deepcopy — вложенные структуры.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Телефонная книга на dict[name] = phone — классический CRUD. Список нельзя использовать как ключ dict (unhashable). Для сортировки списка словарей: sorted(items, key=lambda x: x['score']).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель выбора структуры данных: это выбор алгоритмической сложности заранее, а не после того, как программа начнёт тормозить. dict — это hash map: поиск по ключу в среднем O(1) независимо от размера словаря, потому что Python вычисляет хеш ключа и сразу переходит к нужной ячейке памяти. list — это последовательность: поиск конкретного элемента требует в среднем прохода по половине элементов, то есть O(n) — при 10 записях разница незаметна, при 100 000 — принципиальна.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эта интуиция станет фундаментом для куда более серьёзных решений в будущем: при работе с базами данных (позже в курсе) индекс на колонке — это буквально то же самое hash map/B-tree ускорение, что и dict здесь, только на уровне СУБД, а не языка. Понимание, почему dict.get(key) быстрее [x for x in list if x.name == key], напрямую переносится на понимание, зачем в SQL вообще нужны индексы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: телефонная книга на 10 000 контактов, реализованная как list[dict], требует перебора в среднем 5000 записей на каждый поиск по имени. Та же книга как dict[name] = phone находит контакт за одну операцию хеширования, вне зависимости от того, 10 там записей или миллион — разница становится ощутимой на практике уже при тысячах контактов, а не только в теории алгоритмов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — переносить из JS привычку использовать массивы (list) для всего подряд просто потому, что это самая знакомая структура, не задумываясь о паттерне доступа к данным. Другая тонкость: dict в CPython 3.7+ гарантированно сохраняет порядок вставки ключей, а вот set — нет, это неупорядоченная коллекция, и полагаться на «естественный» порядок при переборе set — источник трудноуловимых различий в поведении между запусками. Именно поэтому реализация телефонной книги в практике дня выбирает dict[name] = phone, а не список словарей — это не произвольная стилистика, а прямое следствие паттерна доступа «найти контакт по точному имени».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: dict для поиска по ключу, list для порядка; выбор структуры — это Big-O.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Телефонная книга: dict[name] = phone, CRUD через меню
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Подсчёт частоты слов в тексте через dict
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Удаление дубликатов из списка через set, сохраняя порядок (bonus)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сортировка списка словарей по ключу score
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. phonebook.py — функции add, remove, search, list_all
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Поиск по частичному совпадению имени
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Валидация формата телефона (простой regex или len)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Телефонная книга persist в JSON-файл

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] .get() вместо KeyError для отсутствующих ключей

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Понимаешь O(1) lookup в dict vs O(n) в list

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Телефонная книга: dict[name] = phone, CRUD через меню
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Подсчёт частоты слов в тексте через dict
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Удаление дубликатов из списка через set, сохраняя порядок (bonus)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Сортировка списка словарей по ключу score
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-15\n\ngit add phonebook.py\n\ngit commit -m "week-15 day-102: телефонная книга и структуры данных"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Использование list как ключа dict — TypeError (unhashable)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          list.sort() vs sorted(list) — in-place vs новый список

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 103 (Пт): Работа с файлами и JSON

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Expense Tracker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Файлы и JSON — мост между программой и диском. Context manager with open(path, 'r', encoding='utf-8') as f: гарантирует закрытие файла даже при исключении. На Windows encoding='utf-8' критичен для кириллицы. Режимы: r чтение, w перезапись, a дополнение в конец.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Модуль json: load/dump для файлов, loads/dumps для строк. ensure_ascii=False сохраняет Unicode, indent=2 делает файл читаемым для человека. Обрабатывай FileNotFoundError (первый запуск) и JSONDecodeError (битый файл) — graceful start важнее краша.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        pathlib.Path — современная альтернатива строковым путям: Path('data') / 'contacts.json'. Atomic write (запись во временный файл + rename) защищает от потери данных при сбое. Для отладки — print, для production — модуль logging с уровнями.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель with open(...) as f: — это гарантия, а не просто удобный синтаксис: контекстный менеджер гарантированно закроет файл (и сбросит буфер записи на диск) даже если между открытием и закрытием произойдёт исключение. Без with пришлось бы вручную оборачивать код в try/finally с явным f.close(), и забытый close() в реальных программах — частая причина «файл вроде записался, но данные потерялись» из-за того, что операционная система буферизует запись и не обязана сбрасывать её на диск немедленно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        JSON-файл в этом контексте — это сериализованный снимок состояния программы между запусками: contacts.json — не просто «файл с данными», а контракт, который читает и пишет твоя программа при каждом старте и завершении. Тот же принцип (сериализация состояния в текстовый формат для передачи или хранения) станет центральным чуть позже в курсе, когда JSON превратится в формат тела HTTP-запросов и ответов между фронтендом и backend — сегодняшнее упражнение с файлом на диске концептуально то же самое, что будущий API-запрос, только без сети.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример скрытой проблемы: на Windows чтение файла без явного encoding='utf-8' может использовать системную кодировку (часто cp1251 для русской локали), из-за чего кириллица в contacts.json превращается в кракозябры не сразу с ошибкой, а тихо — файл открывается, что-то читается, программа не падает, но данные повреждены, и заметить это можно далеко не сразу, особенно если тестировать только с латиницей.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что f.write(data) мгновенно физически записывает байты на диск и что если сразу после write() выключить компьютер или убить процесс, данные точно сохранятся. На самом деле между write() и физической записью на диск стоит буфер операционной системы, и именно закрытие файла (явное или через выход из блока with) инициирует его сброс. В критериях дня явно указано «graceful handling если файл не существует» и «ensure_ascii=False для кириллицы» — оба пункта напрямую защищают от описанных выше проблем при реализации persist телефонной книги в JSON.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: всегда with open и encoding='utf-8'; JSON — контракт persist между запусками.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Расширь телефонную книгу: save/load contacts.json
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Логгер: append строки в app.log с timestamp
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Чтение CSV вручную (split по запятой) → list of dicts
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Backup: копия JSON перед перезаписью
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. storage.py — функции load_contacts(), save_contacts(data)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Graceful start если contacts.json не существует
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Импорт контактов из CSV файла
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Все файлы через with open

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] ensure_ascii=False для кириллицы в JSON

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Graceful handling если файл не существует

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Расширь телефонную книгу: save/load contacts.json
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Логгер: append строки в app.log с timestamp
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Чтение CSV вручную (split по запятой) → list of dicts
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Backup: копия JSON перед перезаписью
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-15\n\ngit add storage.py data/\n\ngit commit -m "week-15 day-103: JSON persist, логгер и CSV import"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Забытый encoding='utf-8' на Windows — кракозябры

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          json.dump без indent — нечитаемый файл для человека

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 104 (Сб): Модули, пакеты, pip

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Expense Tracker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Модули и пакеты масштабируют код за пределы одного файла. import module и from package import name — два стиля; второй удобнее, но может засорить namespace. Пакет — папка с __init__.py (в Python 3.3+ namespace packages возможны без него, но для учебных проектов __init__.py явно). __all__ объявляет публичный API пакета.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        pip install package ставит зависимости в venv; pip freeze > requirements.txt фиксирует версии для воспроизводимых сборок. Pin versions (rich==13.x.x) защищает от неожиданных breaking changes. PyPI — реестр пакетов: requests, rich и тысячи других.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Запуск python -m phonebook.cli выполняет модуль как скрипт с корректными относительными импортами. Избегай циклических импортов: models не должен импортировать cli. Не называй файл json.py — затенишь стандартный модуль.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель пакета: это граница пространства имён плюс явно объявленный публичный API. Папка с __init__.py — не формальность, а сигнал Python «это единый модуль, а не просто набор файлов рядом», а __all__ внутри __init__.py явно перечисляет, что видно снаружи пакета, а что — внутренняя деталь реализации, которую пользователи пакета не должны трогать напрямую.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Разделение на models.py (структуры данных), storage.py (чтение/запись) и cli.py (взаимодействие с пользователем) — это не искусственное упражнение, а миниатюрная версия слоистой архитектуры, которая будет использоваться в любом более крупном приложении: тот же принцип «данные отдельно от способа их хранения, отдельно от интерфейса» лежит в основе backend-фреймворков вроде Django (models/views/serializers) и FastAPI (schemas/crud/routers), с которыми ты столкнёшься позже в курсе.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример пользы requirements.txt с зафиксированными версиями: если сегодня установлен rich==13.7.0, а через полгода на новой машине без pinned версии автоматически поставится rich==14.x с изменённым API, скрипт может сломаться без единого изменения в собственном коде — просто потому что зависимость обновилась. pip freeze > requirements.txt фиксирует не только сам факт использования библиотеки, но и точную версию, гарантируя воспроизводимость окружения на любой машине и через любое время.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — переносить из JS-опыта расслабленное отношение к порядку импортов, где циклические зависимости между модулями иногда «просто работают» из-за особенностей резолвинга ES-модулей или бандлера. В Python циклический импорт (models.py импортирует что-то из cli.py, а cli.py — из models.py) на практике почти гарантированно приводит к ImportError: cannot import name ... (most likely due to a circular import), потому что модуль в момент своего первого импорта ещё не полностью выполнен. Именно поэтому «Ловушки» дня явно требуют однонаправленной иерархии зависимостей (models не импортирует cli) — это правило стоит соблюдать с самого начала разбиения телефонной книги на пакет phonebook/, а не исправлять постфактум, когда импорты уже переплетены.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: пакетная структура + requirements.txt — основа любого Python-проекта.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Разбей телефонную книгу: models.py, storage.py, cli.py
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. pip install rich — красивый вывод таблицы контактов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. requirements.txt с rich==...
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Запуск: python -m phonebook.cli
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Пакет phonebook/ с __init__.py
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Rich Table для list contacts с колонками name, phone
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Цветной вывод ошибок через rich.print
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Пакетная структура с __init__.py

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] requirements.txt актуален

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] rich Table для list contacts

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Разбей телефонную книгу: models.py, storage.py, cli.py
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. pip install rich — красивый вывод таблицы контактов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. requirements.txt с rich==...
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Запуск: python -m phonebook.cli
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-15\n\ngit add phonebook/ requirements.txt\n\ngit commit -m "week-15 day-104: пакет phonebook и rich CLI"\n\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Циклические импорты — раздели слои (models не импортирует cli)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Имя файла json.py — затеняет стандартный модуль

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 105 (Вс): Ревью основ Python

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Expense Tracker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью недели закрепляет фундамент перед CLI Expense Tracker. PEP 8 — не догма, а общий язык: snake_case для функций и переменных, 79–88 символов в строке, два пустых ряда между top-level определениями. python -m py_compile file.py проверяет синтаксис без запуска.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Сравни Python с JavaScript: отступы вместо {}, None вместо null, иная truthiness, явный self в методах. HackerRank/Codewars на Easy уровне тренируют синтаксис вне контекста проекта. Шпаргалка list vs tuple vs dict vs set — шпаргалка на всю карьеру.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CLI Expense Tracker объединяет всё: venv, модули, JSON persist, rich для таблиц, валидацию ввода. README с примерами команд — обязателен. Осмысленные коммиты за 7 дней и тег week-15-done завершают неделю.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Мысленная модель PEP 8: это не эстетическое предпочтение, а общий словарь, снижающий когнитивную нагрузку при чтении чужого (и своего же, через месяц) кода. Когда весь код в индустрии более-менее следует одним соглашениям (snake_case, отступы, пустые строки между определениями), разработчик тратит меньше усилий на «расшифровку» стиля и больше — на понимание логики. Это станет заметно уже при работе в команде или ревью чужого pull request.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Явное сравнение Python и JavaScript, предложенное сегодня, помогает не «смешать» две ментальные модели в одну кашу, а держать их четко разделёнными: явный self первым параметром метода в Python — это осознанный дизайн (в отличие от неявного и местами запутанного this в JS, зависящего от способа вызова функции), и понимание этой разницы предотвращает перенос интуиции о this/биндинге туда, где она не работает.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример пользы практики на HackerRank/Codewars именно сейчас: задачи вне контекста проекта тренируют синтаксис и стандартную библиотеку (sorted, Counter, slicing) в чистом виде, без сопутствующей сложности организации файлов — это как оттачивание отдельных технических приёмов гитариста гаммами, отдельно от разучивания целой песни, коей является Expense Tracker.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать PEP 8 «чисто косметическим» и откладывать форматирование на «потом», а также думать, что раз JavaScript уже знаком, Python-специфичные особенности (truthiness, mutable defaults, is vs ==, единый self) не заслуживают отдельного внимания и «разберутся по ходу». На практике именно эти синтаксические различия — источник большинства мелких, но раздражающих багов у разработчиков, переходящих с JS на Python, а рефакторинг телефонной книги по PEP 8 в практике сегодняшнего дня — не формальность, а шанс закрепить оба набора привычек до того, как начнётся более сложный CLI Expense Tracker, где путаница между двумя языковыми моделями будет стоить дороже времени на исправление.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: Python-проект = venv + модули + persist + README; стиль PEP 8 с первого коммита.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реши 10 задач на HackerRank Python (Easy)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рефакторинг телефонной книги по PEP 8
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Напиши шпаргалку: list vs tuple vs dict vs set
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Начни скелет CLI Expense Trackerexpense_tracker/
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. notes/python-structures.md — шпаргалка структур
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Прогони python -m py_compile на всех модулях
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Тег week-15-done
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] 10 задач HackerRank решены

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Код проходит python -m py_compile без ошибок

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Шпаргалка в notes/python-structures.md

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реши 10 задач на HackerRank Python (Easy)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рефакторинг телефонной книги по PEP 8
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Напиши шпаргалку: list vs tuple vs dict vs set
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Начни скелет CLI Expense Trackerexpense_tracker/
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \ncd learning-log/week-15\n\ngit add notes/ expense_tracker/\n\ngit commit -m "week-15 day-105: HackerRank, PEP 8 и Expense Tracker скелет"\n\n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CLI Expense Tracker — трекер расходов в терминале. Подробное ТЗ: docs/projects.md — Неделя 15.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. \n

                                                                                                                                                                                                                          Категории: food, transport, entertainment, other

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. \n

                                                                                                                                                                                                                          Добавление, список, удаление, сумма по категории, общий итог

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. \n

                                                                                                                                                                                                                          Хранение в expenses.json

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. \n

                                                                                                                                                                                                                          rich — таблица и цветной вывод

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. \n

                                                                                                                                                                                                                          Фильтр по дате (строка YYYY-MM-DD)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          CLI-меню или subcommands: add, list, delete, summary, filter

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Валидация суммы (> 0) и формата даты

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Сводка по категориям с итогами

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Цветной вывод: доход зелёный, расход красный (опционально)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] venv + requirements.txt с pinned versions

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Модульная структура (≥ 3 файла: models, storage, cli)

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Валидация суммы (> 0) и даты

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] README с примерами команд

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] rich Table для списка расходов

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Persist в JSON, переживает перезапуск

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          [ ] Тег week-15-done

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Зачем venv и чем отличается от global Python?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          list vs tuple — когда использовать каждый?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Что такое list comprehension и зачем?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Как работает with open()?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • \n

                                                                                                                                                                                                                          Чем == отличается от is?

                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **CLI Expense Tracker** в `learning-log/week-15/`, осмысленная Git-история, тег `week-15-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nPython основы и CLI\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-15-day-99", "label": "День 99 (Пн): Установка, синтаксис, venv"}, {"id": "week-15-day-100", "label": "День 100 (Вт): Условия, циклы, comprehensions"}, {"id": "week-15-day-101", "label": "День 101 (Ср): Функции и type hints"}, {"id": "week-15-day-102", "label": "День 102 (Чт): Структуры данных — list, tuple, dict, set"}, {"id": "week-15-day-103", "label": "День 103 (Пт): Работа с файлами и JSON"}, {"id": "week-15-day-104", "label": "День 104 (Сб): Модули, пакеты, pip"}, {"id": "week-15-day-105", "label": "День 105 (Вс): Ревью основ Python"}, {"id": "week-15-project", "label": "Проект недели"}, {"id": "week-15-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-15-review", "label": "Проверь себя"}], "text": "Неделя 15: Python — основы Цель недели: освоить синтаксис Python, структуры данных, функции и изолированное окружение. Литература: Python Tutorial , Real Python , «Python. Ускоренный курс» (Теллез), PEP 8 , Python venv Проект недели: см. docs/projects.md Git: минимум 1 осмысленный коммит каждый день в learning-log/week-15/ День 99 (Пн): Установка, синтаксис, venv Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1.5ч практика (MVP) · ~10м Git Связь с проектом: шаг к CLI Expense Tracker Теория Python — первый шаг в backend после фронтенда. Установка с python.org (или py launcher на Windows) и проверка python --version — база. Главная привычка с первого дня: виртуальное окружение python -m venv .venv изолирует зависимости проекта от системного Pyt…"} \ No newline at end of file diff --git a/docs/weeks/16.json b/docs/weeks/16.json index 25c9a25..77d594a 100644 --- a/docs/weeks/16.json +++ b/docs/weeks/16.json @@ -1 +1 @@ -{"id": "week-16", "title": "Python OOP", "fullTitle": "Неделя 16: Python — ООП, алгоритмы, файлы", "html": "

                                                                                                                                                                                                                        Неделя 16: Python — ООП, алгоритмы, файлы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: освоить объектно-ориентированный Python, оценку сложности и работу с файловой системой.\nЛитература: Python OOP, Real Python — pathlib, Big-O Cheat Sheet\nПроект недели: CLI Task Manager (SQLite) — классы Task, TaskRepository, CRUD через sqlite3, теги many-to-many.\nGit: папка learning-log/week-16/, минимум 1 осмысленный коммит в день; к концу недели тег week-16-done.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 106 (Пн): Классы и объекты

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Объектно-ориентированное программирование в Python объединяет данные и поведение в одной сущности — классе. class BankAccount: с методом __init__(self, ...) инициализирует экземпляр; self — ссылка на конкретный объект. Атрибуты экземпляра (self.balance) хранят состояние; атрибуты класса (currency = 'RUB') — общие настройки для всех счетов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Три вида методов: обычные (работают с self), @classmethod (альтернативные конструкторы, фабрики), @staticmethod (утилиты без доступа к экземпляру). __str__ — для пользователя (print(account)), __repr__ — для отладки в REPL, должен однозначно идентифицировать объект.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Инкапсуляция в Python — соглашение: префикс _balance сигнализирует «не трогай снаружи», @property даёт контролируемое чтение без прямой мутации. Type hints на методах помогают IDE ловить ошибки до запуска. Баланс меняется только через deposit и withdraw — это и есть защита инвариантов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: класс = данные + поведение; self обязателен; инкапсуляция через методы, не публичные поля.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Класс BankAccount: deposit, withdraw, balance, защита от отрицательного баланса
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Класс Transaction с датой, суммой, типом (deposit / withdraw)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Список счетов, перевод между счетами с записью двух транзакций
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. print(account) использует __str__, в отладке — repr(account)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Добавь @property balance — чтение без setter, изменение только через методы
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Напиши 3 unit-подобных assert-теста в if __name__ == \"__main__\" для happy path и ошибок
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Инкапсуляция: баланс не меняется напрямую снаружи\n- [ ] __repr__ однозначно идентифицирует объект\n- [ ] Type hints на аргументах и return всех публичных методов

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Класс BankAccount: deposit, withdraw, balance, защита от отрицательного баланса
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Класс Transaction с датой, суммой, типом (deposit / withdraw)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Список счетов, перевод между счетами с записью двух транзакций
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-16/git commit -m \"week 16 day 106: BankAccount and Transaction classes\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Забытый self в методах — TypeError
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Публичные атрибуты вместо свойств — нарушение инкапсуляции
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 107 (Вт): Наследование, композиция, dataclasses

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Наследование (class Savings(BankAccount)) расширяет базовый класс: дочерний получает методы родителя и добавляет свои. super().__init__(...) вызывает конструктор родителя — забудешь, и поля родителя не инициализируются. Но глубокие иерархии хрупки: предпочитай композицию («has-a»), когда объект содержит другие объекты, а не наследует их («is-a»).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Portfolio с list[Account] — композиция: портфель не «является» счётом, он их «содержит». Это гибче, чем class Portfolio(Account). @dataclass автогенерирует __init__, __repr__, __eq__ для DTO без сложного поведения — идеально для Expense или Task.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        __post_init__ валидирует поля после создания dataclass (сумма > 0). frozen=True делает объект immutable — безопасен как ключ dict. ABC (ABC, @abstractmethod) задаёт контракт для TaskRepository — подкласс обязан реализовать методы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: композиция чаще наследования; dataclass — для данных, class — для поведения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. SavingsAccount с interest_rate, метод apply_interest() через super()
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Portfolio содержит list[Account] — композиция, не наследование
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Рефакторинг @dataclass Expense из недели 15 с __post_init__ валидацией
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Абстрактный BaseRepository с get, add, delete — заготовка для SQLite
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Сравни размер кода: dataclass vs ручной класс для Expense
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Задокументируй в notes/oop.md: когда наследование, когда композиция
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] super().__init__() в дочернем классе\n- [ ] Portfolio не наследует Account — композиция\n- [ ] dataclass с валидацией суммы > 0

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. SavingsAccount с interest_rate, метод apply_interest() через super()
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Portfolio содержит list[Account] — композиция, не наследование
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Рефакторинг @dataclass Expense из недели 15 с __post_init__ валидацией
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-16/git commit -m \"week 16 day 107: inheritance, composition, dataclasses\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Глубокая иерархия наследования — хрупкий дизайн
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • dataclass mutable по умолчанию — frozen=True для immutable
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 108 (Ср): Магические методы и итераторы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Магические методы (dunder) делают объекты «питоничными»: __len__ для len(obj), __getitem__ для obj[i], __contains__ для x in obj. Класс Playlist с этими методами ведёт себя как встроенная коллекция — пользователь API не знает о внутреннем list.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Итератор-протокол: __iter__ возвращает объект с __next__, который выдаёт элементы или бросает StopIteration. Generator function с yield — ленивая последовательность: fibonacci(n) не хранит весь ряд в RAM. Generator read_log_lines(path) читает файл построчно — O(1) память на строку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        __eq__ определяет равенство; если переопределяешь его и хочешь использовать объекты в set/dict, продумай __hash__ (или используй frozen dataclass). __lt__ позволяет sorted(transactions) без key-функции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: dunder-методы — контракт с Python; generators — ленивость и экономия памяти.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Класс Playlist с __len__, __getitem__, итерацией по трекам
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Generator fibonacci(n) — первые n чисел без списка в памяти
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Playlist поддерживает for track in playlist и len(playlist)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Перегрузка == для Transaction по id; проверь поведение в set
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Generator read_log_lines(path) — построчное чтение большого файла
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Напиши в notes/dunder.md три dunder-метода и зачем они нужны
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Playlist итерируется в for-loop\n- [ ] Generator не хранит весь ряд Фибоначчи в памяти\n- [ ] __eq__ согласован с hash (если используешь в set)

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Класс Playlist с __len__, __getitem__, итерацией по трекам
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Generator fibonacci(n) — первые n чисел без списка в памяти
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Playlist поддерживает for track in playlist и len(playlist)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-16/git commit -m \"week 16 day 108: dunder methods and generators\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • __eq__ без __hash__ — объект не hashable для set/dict keys
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Бесконечный generator без условия остановки
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 109 (Чт): Алгоритмы и Big O

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Big O описывает, как растёт время или память при увеличении входа, а не абсолютные миллисекунды. O(1) — константа, O(log n) — бинарный поиск, O(n) — один проход, O(n log n) — эффективная сортировка, O(n²) — вложенные циклы. Выбор структуры данных важнее микрооптимизаций: dict lookup O(1) в среднем vs list O(n).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Linear search перебирает все элементы; binary search требует отсортированный массив и делит пополам — O(log n). На 10⁶ элементов разница колоссальна. Two Sum: brute force O(n²) vs hash map O(n) — классический пример, когда дополнительная память покупает скорость.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Встроенная сортировка Python (Timsort) — O(n log n); bubble sort O(n²) — учебный, не production. list.append амортизированно O(1), но иногда O(n) при resize. VisuAlgo помогает увидеть рост операций. Замеры через time.perf_counter() убеждают лучше теории.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: сначала правильная структура данных и алгоритм, потом микрооптимизации.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реализуй linear search и binary search (sorted list)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Замерь время на списке 10⁴ и 10⁶ элементов (time.perf_counter)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Two Sum: brute force O(n²) vs hash map O(n) — сравни замеры
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Таблица в notes/big-o.md: операция → сложность для list, dict, set
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Реши на бумаге: сложность вложенных циклов и dict.get в цикле
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Опционально: визуализируй binary search на VisuAlgo
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Binary search работает только на sorted input\n- [ ] Замеры подтверждают разницу O(n) vs O(n²)\n- [ ] Two Sum hash map решение за один проход

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реализуй linear search и binary search (sorted list)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Замерь время на списке 10⁴ и 10⁶ элементов (time.perf_counter)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Two Sum: brute force O(n²) vs hash map O(n) — сравни замеры
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-16/git commit -m \"week 16 day 109: Big O benchmarks and Two Sum\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Binary search на unsorted list — неверный результат
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Путаница best/average/worst case — указывай worst
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 110 (Пт): pathlib и работа с файловой системой

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        pathlib.Path — объектный API для путей вместо конкатенации строк и os.path.join. Оператор / склеивает кроссплатформенно: Path('data') / 'tasks.db'. read_text(), write_text(), exists(), glob('*.py'), rglob('**/*.py') покрывают 90% задач с файловой системой.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Path(__file__).parent даёт каталог скрипта — надёжнее относительных путей от cwd, который меняется при запуске из другой папки. shutil.copy, move, rmtree — операции над деревом. Context manager with path.open() гарантирует закрытие файла.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Скрипт organize.py сортирует файлы по расширению — практика обхода директорий. --dry-run показывает план без изменений — хорошая привычка для деструктивных операций. PermissionError на системных файлах логируй, не падай целиком.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: Path(__file__).parent — якорь для путей; pathlib вместо строк.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Скрипт organize.py — сортирует файлы по расширению в подпапки
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рекурсивный поиск *.py через rglob
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Подсчёт размера директории в MB
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Флаг --dry-run: показать план без перемещения
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Обработка PermissionError и логирование пропущенных файлов
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Подготовь data/ для SQLite БД проекта недели
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Только pathlib, не os.path (кроме env vars)\n- [ ] Dry-run режим работает\n- [ ] Обработка PermissionError

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Скрипт organize.py — сортирует файлы по расширению в подпапки
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рекурсивный поиск *.py через rglob
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Подсчёт размера директории в MB
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-16/git commit -m \"week 16 day 110: pathlib organize script\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • path.write_text() перезаписывает без confirm — сделай backup
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Относительные пути зависят от cwd — используй Path(__file__).parent
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 111 (Сб): regex и обработка текстовых логов

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Регулярные выражения — мини-язык поиска по тексту. Модуль re: match — с начала строки, search — везде, findall — все совпадения, sub — замена. Raw-строки r\"\\d+\" — backslash не экранируется Python. Группы () и именованные (?P<name>...) извлекают поля из лога.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Построчное чтение большого файла — O(1) память на строку; не загружай гигабайтный лог в read(). re.compile(pattern) переиспользуй в цикле — быстрее, чем компилировать каждый раз. regex101.com — тестируй паттерн до вставки в код.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Парсер server.log с named groups для timestamp, level, message — типичная задача DevOps/junior backend. Топ ERROR по часам — агрегация в dict. Замена IP на [REDACTED]re.sub. Жадный .* может «съесть» лишнее — будь осторожен с квантификаторами.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: для поиска везде — search, не match; большие файлы — построчно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Генератор mock server.log (1000 строк: timestamp, level, message)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Парсер: извлечь все ERROR с датой через named groups
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Топ-5 часов с наибольшим числом ERROR
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Замена IP-адресов на [REDACTED] в копии лога
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. CLI: python parse_log.py server.log --level ERROR
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сохрани итоговую статистику в reports/error-summary.txt
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Парсинг построчно (memory-efficient)\n- [ ] regex с named groups для timestamp и level\n- [ ] Итоговая статистика в читаемом виде

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Генератор mock server.log (1000 строк: timestamp, level, message)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Парсер: извлечь все ERROR с датой через named groups
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Топ-5 часов с наибольшим числом ERROR
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-16/git commit -m \"week 16 day 111: log parser with regex\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • re.match только с начала строки — для поиска везде re.search
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Жадные квантификаторы .* — неожиданные совпадения
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 112 (Вс): Ревью ООП и алгоритмов

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью ООП и алгоритмов готовит к SQLite-проекту недели. SOLID на junior-уровне: Single Responsibility — один класс, одна причина для изменения; Open/Closed — расширяй через композицию, не правь базовый класс везде. Не усложняй: простой скрипт — функции + dataclasses, сложный домен — классы с поведением.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Code smells: god class на 500 строк, дублирование, magic numbers без констант. LeetCode Easy (Two Sum, Valid Parentheses) закрепляет структуры данных вне pet-проекта. Рефакторинг Expense Tracker на Expense + ExpenseStore — мост к TaskRepository.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подготовь venv для недели 17 с psycopg2-binary и python-dotenv. Конспект Big O на одну страницу — пригодится при EXPLAIN и выборе индексов. Тег week-16-done на финальном коммите.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: ООП — инструмент, не цель; простые данные — dataclass, сложная логика — классы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реши 3 задачи LeetCode Easy: Two Sum, Valid Parentheses, Merge Sorted Array
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рефакторинг Expense Tracker на классы Expense, ExpenseStore
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. ExpenseStore.save() / load() через pathlib + JSON
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Напиши ответы в notes/oop-review.md: 3 магических метода и зачем
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Конспект Big O на 1 страницу с примерами из недели
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай venv и requirements.txt для недели 17
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] 3 LeetCode задачи приняты\n- [ ] ExpenseStore с save/load через pathlib\n- [ ] Конспект Big O на 1 страницу

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реши 3 задачи LeetCode Easy: Two Sum, Valid Parentheses, Merge Sorted Array
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рефакторинг Expense Tracker на классы Expense, ExpenseStore
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. ExpenseStore.save() / load() через pathlib + JSON
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-16/git commit -m \"week 16 day 112: OOP review and LeetCode\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поставь тег: git tag week-16-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CLI Task Manager (SQLite) — расширенная версия с ООП и реляционной БД. Полное описание: docs/projects.md — неделя 16.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Архитектура

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Классы: Task, Tag, TaskRepository (SQLite), TaskCLI (меню и ввод)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Схема БД: tasks, tags, task_tags (many-to-many)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CRUD: создание, список, обновление статуса, удаление, поиск по тегу
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Транзакции: try/except + conn.rollback() при ошибке
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. UI: rich — таблица задач, цвет по статусу (pending / done)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Требования

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • ORM не используем — чистый sqlite3 (SQLAlchemy на нед. 18)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Все SQL с placeholders (?), никогда f-string в запросах
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • schema.sql + seed с 5+ задачами и 3+ тегами
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • README: установка, команды CLI, ER-диаграмма схемы
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • .env не нужен — SQLite локальный файл data/tasks.db
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • python -m task_cli или python main.py запускает интерактивное меню
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поиск и фильтр по статусу и тегу работают
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Many-to-many: задача может иметь несколько тегов
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Транзакция откатывается при нарушении FK
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • README + схема БД + скриншот rich-таблицы
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Тег week-16-done на финальном коммите
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • __init__ vs __new__ — в чём разница (обзор)?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • list.pop(0) — какая сложность и почему?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Когда dataclass, когда полноценный class?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • pathlib vs os.path — что предпочтительнее в 2024+?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как защититься от SQL injection в sqlite3?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **CLI Task Manager** в `learning-log/week-16/`, осмысленная Git-история, тег `week-16-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nPython ООП, SQLite, алгоритмы\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-16-day-106", "label": "День 106 (Пн): Классы и объекты"}, {"id": "week-16-day-107", "label": "День 107 (Вт): Наследование, композиция, dataclasses"}, {"id": "week-16-day-108", "label": "День 108 (Ср): Магические методы и итераторы"}, {"id": "week-16-day-109", "label": "День 109 (Чт): Алгоритмы и Big O"}, {"id": "week-16-day-110", "label": "День 110 (Пт): pathlib и работа с файловой системой"}, {"id": "week-16-day-111", "label": "День 111 (Сб): regex и обработка текстовых логов"}, {"id": "week-16-day-112", "label": "День 112 (Вс): Ревью ООП и алгоритмов"}, {"id": "week-16-project", "label": "Проект недели"}, {"id": "week-16-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-16-review", "label": "Проверь себя"}], "text": "Неделя 16: Python — ООП, алгоритмы, файлы Цель недели: освоить объектно-ориентированный Python, оценку сложности и работу с файловой системой. Литература: Python OOP , Real Python — pathlib , Big-O Cheat Sheet Проект недели: CLI Task Manager (SQLite) — классы Task , TaskRepository , CRUD через sqlite3 , теги many-to-many. Git: папка learning-log/week-16/ , минимум 1 осмысленный коммит в день; к концу недели тег week-16-done . День 106 (Пн): Классы и объекты Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к CLI Task Manager Теория Объектно-ориентированное программирование в Python объединяет данные и поведение в одной сущности — классе. class BankAccount: с методом __init__(self, ...) инициал…"} \ No newline at end of file +{"id": "week-16", "title": "Python OOP", "fullTitle": "Неделя 16: Python — ООП, алгоритмы, файлы", "html": "

                                                                                                                                                                                                                        Неделя 16: Python — ООП, алгоритмы, файлы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: освоить объектно-ориентированный Python, оценку сложности и работу с файловой системой.\nЛитература: Python OOP, Real Python — pathlib, Big-O Cheat Sheet\nПроект недели: CLI Task Manager (SQLite) — классы Task, TaskRepository, CRUD через sqlite3, теги many-to-many.\nGit: папка learning-log/week-16/, минимум 1 осмысленный коммит в день; к концу недели тег week-16-done.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 106 (Пн): Классы и объекты

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Объектно-ориентированное программирование в Python объединяет данные и поведение в одной сущности — классе. class BankAccount: с методом __init__(self, ...) инициализирует экземпляр; self — ссылка на конкретный объект. Атрибуты экземпляра (self.balance) хранят состояние; атрибуты класса (currency = 'RUB') — общие настройки для всех счетов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Три вида методов: обычные (работают с self), @classmethod (альтернативные конструкторы, фабрики), @staticmethod (утилиты без доступа к экземпляру). __str__ — для пользователя (print(account)), __repr__ — для отладки в REPL, должен однозначно идентифицировать объект.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Инкапсуляция в Python — соглашение: префикс _balance сигнализирует «не трогай снаружи», @property даёт контролируемое чтение без прямой мутации. Type hints на методах помогают IDE ловить ошибки до запуска. Баланс меняется только через deposit и withdraw — это и есть защита инвариантов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Полезная ментальная модель: класс — это чертёж, а объект — конкретное здание, построенное по этому чертежу. Чертёж один, зданий может быть тысячи, и каждое хранит собственное состояние в self.__dict__, не разделяя его с соседями. Атрибуты класса (currency = 'RUB') — это табличка на воротах всего микрорайона: изменишь её через класс — увидят все объекты сразу. Именно поэтому mutable атрибут класса (список, словарь по умолчанию) — частая причина неожиданных багов: все экземпляры незаметно «делят» одну и ту же коллекцию, если её не создать в __init__.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эта конструкция не абстрактное упражнение ради экзамена: ровно тот же синтаксис class + __init__ + self появится в моделях SQLAlchemy на неделе 18 (class Book(Base): id: Mapped[int]) и в Pydantic-схемах FastAPI — ООП станет языком, на котором описана вся архитектура backend. На примере BankAccount: вызов acc.deposit(100) под капотом эквивалентен BankAccount.deposit(acc, 100)self это просто первый позиционный аргумент, который Python автоматически подставляет при обращении через точку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение новичков — считать @staticmethod и @classmethod взаимозаменяемыми. staticmethod не получает ни self, ни cls и годится для чистых утилит (BankAccount.validate_amount(100)); classmethod получает cls и чаще служит альтернативным конструктором (Account.from_dict(data)), который должен корректно работать и для наследников. Ещё одна ловушка — путать __str__ и __repr__: если определить только __repr__, print(obj) использует именно его, но для логов и REPL желательно, чтобы repr можно было почти дословно вставить обратно в код как валидное выражение. В практике дня это проверяется напрямую: __repr__ для Transaction должен однозначно показывать id, сумму и тип — иначе баг по логу не найти.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: класс = данные + поведение; self обязателен; инкапсуляция через методы, не публичные поля.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Класс BankAccount: deposit, withdraw, balance, защита от отрицательного баланса
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Класс Transaction с датой, суммой, типом (deposit / withdraw)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Список счетов, перевод между счетами с записью двух транзакций
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. print(account) использует __str__, в отладке — repr(account)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Добавь @property balance — чтение без setter, изменение только через методы
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Напиши 3 unit-подобных assert-теста в if __name__ == \"__main__\" для happy path и ошибок
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Инкапсуляция: баланс не меняется напрямую снаружи\n- [ ] __repr__ однозначно идентифицирует объект\n- [ ] Type hints на аргументах и return всех публичных методов

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Класс BankAccount: deposit, withdraw, balance, защита от отрицательного баланса
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Класс Transaction с датой, суммой, типом (deposit / withdraw)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Список счетов, перевод между счетами с записью двух транзакций
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-16/git commit -m \"week 16 day 106: BankAccount and Transaction classes\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Забытый self в методах — TypeError
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Публичные атрибуты вместо свойств — нарушение инкапсуляции
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 107 (Вт): Наследование, композиция, dataclasses

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Наследование (class Savings(BankAccount)) расширяет базовый класс: дочерний получает методы родителя и добавляет свои. super().__init__(...) вызывает конструктор родителя — забудешь, и поля родителя не инициализируются. Но глубокие иерархии хрупки: предпочитай композицию («has-a»), когда объект содержит другие объекты, а не наследует их («is-a»).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Portfolio с list[Account] — композиция: портфель не «является» счётом, он их «содержит». Это гибче, чем class Portfolio(Account). @dataclass автогенерирует __init__, __repr__, __eq__ для DTO без сложного поведения — идеально для Expense или Task.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        __post_init__ валидирует поля после создания dataclass (сумма > 0). frozen=True делает объект immutable — безопасен как ключ dict. ABC (ABC, @abstractmethod) задаёт контракт для TaskRepository — подкласс обязан реализовать методы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель для выбора между наследованием и композицией — LEGO-конструктор. Наследование — это «разблокировать улучшенную версию детали» с дополнительными способностями родителя (SavingsAccount умеет всё, что умеет BankAccount, плюс начисление процентов). Композиция — это «собрать модель из готовых независимых деталей» (Portfolio не является счётом, он содержит счета). Правило Liskov: наследуй только тогда, когда дочерний объект можно подставить всюду, где ожидается родительский, не сломав поведение. Если такой подстановки нет — это не «is-a», а признак того, что нужна композиция.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно позже: абстрактный BaseRepository с @abstractmethod get/add/delete, который ты создаёшь сегодня, — это тот же паттерн, что и Repository/Service слои в FastAPI-проекте недели 18 и layered-архитектура Express на неделе 19. Понимание ABC-контракта здесь напрямую объясняет, зачем в будущем API определяют интерфейсы, которые обязаны реализовать разные backend'ы (SQLite сегодня, PostgreSQL завтра).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частая ошибка новичков — наследовать ради переиспользования кода, а не ради логической связи «is-a», что приводит к глубоким и хрупким иерархиям (Manager(Employee(Person)) с десятком переопределённых методов). Другая типичная ловушка — забыть super().__init__(...) в дочернем классе: тогда поля родителя просто не инициализируются, и на первый взгляд валидный код падает с AttributeError при первом обращении к унаследованному атрибуту. В практике дня это проверяется прямо: SavingsAccount должен вызывать super().__init__() и при этом оставаться взаимозаменяемым с обычным BankAccount везде, где ожидается счёт. Практическое правило для выбора: если ответ на вопрос «B — это разновидность A?» звучит естественно на русском языке, скорее всего перед тобой наследование; если естественнее звучит «B содержит/использует A», выбирай композицию.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: композиция чаще наследования; dataclass — для данных, class — для поведения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. SavingsAccount с interest_rate, метод apply_interest() через super()
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Portfolio содержит list[Account] — композиция, не наследование
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Рефакторинг @dataclass Expense из недели 15 с __post_init__ валидацией
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Абстрактный BaseRepository с get, add, delete — заготовка для SQLite
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Сравни размер кода: dataclass vs ручной класс для Expense
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Задокументируй в notes/oop.md: когда наследование, когда композиция
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] super().__init__() в дочернем классе\n- [ ] Portfolio не наследует Account — композиция\n- [ ] dataclass с валидацией суммы > 0

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. SavingsAccount с interest_rate, метод apply_interest() через super()
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Portfolio содержит list[Account] — композиция, не наследование
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Рефакторинг @dataclass Expense из недели 15 с __post_init__ валидацией
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-16/git commit -m \"week 16 day 107: inheritance, composition, dataclasses\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Глубокая иерархия наследования — хрупкий дизайн
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • dataclass mutable по умолчанию — frozen=True для immutable
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 108 (Ср): Магические методы и итераторы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Магические методы (dunder) делают объекты «питоничными»: __len__ для len(obj), __getitem__ для obj[i], __contains__ для x in obj. Класс Playlist с этими методами ведёт себя как встроенная коллекция — пользователь API не знает о внутреннем list.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Итератор-протокол: __iter__ возвращает объект с __next__, который выдаёт элементы или бросает StopIteration. Generator function с yield — ленивая последовательность: fibonacci(n) не хранит весь ряд в RAM. Generator read_log_lines(path) читает файл построчно — O(1) память на строку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        __eq__ определяет равенство; если переопределяешь его и хочешь использовать объекты в set/dict, продумай __hash__ (или используй frozen dataclass). __lt__ позволяет sorted(transactions) без key-функции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: dunder-методы — это «розетки» единого стандарта Python. Реализуешь __len__, __getitem__, __iter__ — и твой объект тут же подключается к экосистеме len(), циклов for, срезов, распаковки, как электроприбор со стандартной вилкой вместо самодельного разъёма. Пользователю Playlist не нужно знать, что внутри list — он просто пишет for track in playlist, как для любой встроенной коллекции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это важно позже: итератор-протокол лежит в основе курсоров баз данных — результат SQL-запроса в SQLAlchemy (неделя 18) и pool.query() в Node (неделя 19) тоже по сути итерируемые последовательности строк. А ленивые generator'ы — прямой путь к обработке данных, которые не помещаются в память целиком: тот же приём понадобится при построчном парсинге логов (день 111) и при потоковой отдаче больших файлов из API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что generator можно «перемотать» и пройти повторно: после первого полного обхода for x in fibonacci(10) генератор исчерпан, второй for по тому же объекту ничего не вернёт — нужно создавать новый вызов функции-генератора заново. Также важно не путать __eq__ без согласованного __hash__: если переопределить только __eq__, объект по умолчанию становится unhashable, и попытка положить его в set бросит TypeError — это прямо проверяется в критериях практики дня. Хорошее эмпирическое правило: если объект по смыслу — коллекция или последовательность, реализуй __len__/__iter__, а не заставляй пользователя лезть во внутренний атрибут через playlist.tracks — так API остаётся стабильным, даже если внутреннее хранилище позже сменится с list на что-то другое. Generator function с yield стоит воспринимать как функцию, которая «замораживается» после каждого значения и продолжает выполнение ровно с того места, где остановилась, при следующем вызове next() — в этом смысле она куда ближе к сопрограмме, чем к обычной функции, возвращающей единственный результат.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: dunder-методы — контракт с Python; generators — ленивость и экономия памяти.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Класс Playlist с __len__, __getitem__, итерацией по трекам
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Generator fibonacci(n) — первые n чисел без списка в памяти
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Playlist поддерживает for track in playlist и len(playlist)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Перегрузка == для Transaction по id; проверь поведение в set
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Generator read_log_lines(path) — построчное чтение большого файла
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Напиши в notes/dunder.md три dunder-метода и зачем они нужны
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Playlist итерируется в for-loop\n- [ ] Generator не хранит весь ряд Фибоначчи в памяти\n- [ ] __eq__ согласован с hash (если используешь в set)

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Класс Playlist с __len__, __getitem__, итерацией по трекам
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Generator fibonacci(n) — первые n чисел без списка в памяти
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Playlist поддерживает for track in playlist и len(playlist)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-16/git commit -m \"week 16 day 108: dunder methods and generators\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • __eq__ без __hash__ — объект не hashable для set/dict keys
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Бесконечный generator без условия остановки
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 109 (Чт): Алгоритмы и Big O

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Big O описывает, как растёт время или память при увеличении входа, а не абсолютные миллисекунды. O(1) — константа, O(log n) — бинарный поиск, O(n) — один проход, O(n log n) — эффективная сортировка, O(n²) — вложенные циклы. Выбор структуры данных важнее микрооптимизаций: dict lookup O(1) в среднем vs list O(n).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Linear search перебирает все элементы; binary search требует отсортированный массив и делит пополам — O(log n). На 10⁶ элементов разница колоссальна. Two Sum: brute force O(n²) vs hash map O(n) — классический пример, когда дополнительная память покупает скорость.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Встроенная сортировка Python (Timsort) — O(n log n); bubble sort O(n²) — учебный, не production. list.append амортизированно O(1), но иногда O(n) при resize. VisuAlgo помогает увидеть рост операций. Замеры через time.perf_counter() убеждают лучше теории.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель Big O — это не секундомер, а вопрос «как растёт очередь в кассе, если покупателей стало в 10 раз больше». O(1) — очередь не меняется независимо от числа покупателей (хеш-таблица); O(n) — очередь растёт пропорционально (один проход по списку); O(n²) — при удвоении входа время растёт вчетверо (вложенные циклы, попарные сравнения). Асимптотика описывает поведение на больших n, а не абсолютные миллисекунды на конкретной машине.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это критично для следующей недели: индекс в PostgreSQL (день 117) — это ровно превращение поиска из O(n) (полный перебор, Seq Scan) в O(log n) (B-tree, Index Scan). Без сегодняшнего понимания разницы между линейным и логарифмическим ростом объяснение EXPLAIN ANALYZE останется магией, а с ним — станет очевидным фактом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что алгоритм с лучшей асимптотикой всегда быстрее на практике: у O(n log n) может быть больший constant factor, и на маленьких n (скажем, 20 элементов) простой O(n²) bubble sort иногда обгоняет сложную сортировку из-за накладных расходов. Другая ошибка — путать best/average/worst case, говоря «O(n)» про алгоритм, который в худшем случае деградирует до O(n²) (как naive quicksort на отсортированном входе). В практике дня это проверяется замерами: разница между linear и binary search становится заметной именно на больших объёмах — 10⁶ элементов, а не 10. Two Sum — хороший тест на этот сдвиг мышления: наивное решение перебирает все пары чисел (O(n²)), а решение через хеш-таблицу проходит по массиву один раз, на каждом шаге проверяя, не встречалось ли уже нужное дополнение — обмен памяти (дополнительный словарь) на скорость (O(n)) в чистом виде.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: сначала правильная структура данных и алгоритм, потом микрооптимизации.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реализуй linear search и binary search (sorted list)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Замерь время на списке 10⁴ и 10⁶ элементов (time.perf_counter)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Two Sum: brute force O(n²) vs hash map O(n) — сравни замеры
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Таблица в notes/big-o.md: операция → сложность для list, dict, set
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Реши на бумаге: сложность вложенных циклов и dict.get в цикле
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Опционально: визуализируй binary search на VisuAlgo
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Binary search работает только на sorted input\n- [ ] Замеры подтверждают разницу O(n) vs O(n²)\n- [ ] Two Sum hash map решение за один проход

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реализуй linear search и binary search (sorted list)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Замерь время на списке 10⁴ и 10⁶ элементов (time.perf_counter)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Two Sum: brute force O(n²) vs hash map O(n) — сравни замеры
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-16/git commit -m \"week 16 day 109: Big O benchmarks and Two Sum\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Binary search на unsorted list — неверный результат
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Путаница best/average/worst case — указывай worst
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 110 (Пт): pathlib и работа с файловой системой

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        pathlib.Path — объектный API для путей вместо конкатенации строк и os.path.join. Оператор / склеивает кроссплатформенно: Path('data') / 'tasks.db'. read_text(), write_text(), exists(), glob('*.py'), rglob('**/*.py') покрывают 90% задач с файловой системой.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Path(__file__).parent даёт каталог скрипта — надёжнее относительных путей от cwd, который меняется при запуске из другой папки. shutil.copy, move, rmtree — операции над деревом. Context manager with path.open() гарантирует закрытие файла.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Скрипт organize.py сортирует файлы по расширению — практика обхода директорий. --dry-run показывает план без изменений — хорошая привычка для деструктивных операций. PermissionError на системных файлах логируй, не падай целиком.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: Path — не строка, а объект-значение, описывающий местоположение, а не сам файл. Операции над ним (/, .parent, .suffix) собирают новый путь, не трогая диск, пока явно не вызван read_text(), write_text() или unlink(). Это разделение «описать путь» и «выполнить операцию с файлом» снижает риск случайных побочных эффектов по сравнению со строковой конкатенацией os.path.join.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это пригодится дальше: путь к SQLite-файлу проекта этой недели (data/tasks.db), путь к статике в FastAPI-приложении недели 18, путь к файлу конфигурации в Express на неделе 19 — везде нужен надёжный якорь Path(__file__).parent, который не зависит от того, откуда запущен скрипт. Привычка мыслить путями как объектами, а не строками, переносится в любой стек, включая pathlib-аналоги в других языках.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что path.write_text() или shutil.move() создадут промежуточные папки автоматически: если родительской директории нет, операция упадёт с FileNotFoundError, и нужно явно вызвать path.parent.mkdir(parents=True, exist_ok=True). Ещё одна типичная ошибка — полагаться на относительные пути от текущей директории запуска (Path('data/tasks.db')), которая меняется в зависимости от того, откуда вызван скрипт — отсюда обязательность --dry-run в практике: он заставляет сначала увидеть реальные абсолютные пути, прежде чем что-то удалять или перемещать. Это тот же принцип «сначала покажи план, потом выполняй», который применяется в миграциях БД и деплой-скриптах: возможность безопасно посмотреть, что произойдёт, без реального изменения состояния — признак зрелого инструмента, а не только учебного скрипта. Отдельно стоит отметить glob('*.py') против rglob('**/*.py'): первый ищет только в текущей папке, второй — рекурсивно во всех вложенных, и путаница между ними — частая причина «скрипт ничего не находит», хотя нужные файлы явно есть где-то в дереве проекта.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: Path(__file__).parent — якорь для путей; pathlib вместо строк.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Скрипт organize.py — сортирует файлы по расширению в подпапки
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рекурсивный поиск *.py через rglob
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Подсчёт размера директории в MB
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Флаг --dry-run: показать план без перемещения
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Обработка PermissionError и логирование пропущенных файлов
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Подготовь data/ для SQLite БД проекта недели
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Только pathlib, не os.path (кроме env vars)\n- [ ] Dry-run режим работает\n- [ ] Обработка PermissionError

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Скрипт organize.py — сортирует файлы по расширению в подпапки
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рекурсивный поиск *.py через rglob
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Подсчёт размера директории в MB
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-16/git commit -m \"week 16 day 110: pathlib organize script\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • path.write_text() перезаписывает без confirm — сделай backup
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Относительные пути зависят от cwd — используй Path(__file__).parent
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 111 (Сб): regex и обработка текстовых логов

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Регулярные выражения — мини-язык поиска по тексту. Модуль re: match — с начала строки, search — везде, findall — все совпадения, sub — замена. Raw-строки r\"\\d+\" — backslash не экранируется Python. Группы () и именованные (?P<name>...) извлекают поля из лога.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Построчное чтение большого файла — O(1) память на строку; не загружай гигабайтный лог в read(). re.compile(pattern) переиспользуй в цикле — быстрее, чем компилировать каждый раз. regex101.com — тестируй паттерн до вставки в код.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Парсер server.log с named groups для timestamp, level, message — типичная задача DevOps/junior backend. Топ ERROR по часам — агрегация в dict. Замена IP на [REDACTED]re.sub. Жадный .* может «съесть» лишнее — будь осторожен с квантификаторами.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: регулярное выражение — это мини-язык программирования, компилируемый в конечный автомат (finite state machine), который «читает» строку символ за символом и решает, продолжать совпадение или откатиться назад. Понимание этого объясняет и жадность квантификаторов (.* пытается захватить максимум, потом «отдаёт» посимвольно, если весь паттерн не совпал), и почему сложные вложенные квантификаторы могут вызывать катастрофический backtracking — экспоненциальное замедление на определённых входах.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Разбор логов — не учебная задача ради задачи: это одна из самых частых обязанностей junior/DevOps-инженера в первые месяцы работы, а извлечение структурированных полей через named groups — тот же навык, что валидация формата email или телефона регулярным выражением внутри Pydantic (неделя 18) или Zod (неделя 19), которые используют regex под капотом для паттернов вроде pattern=r'^\\+?\\d{10,15}$'.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — использовать regex там, где нужен полноценный парсер: для вложенных структур вроде HTML или JSON регулярка либо не справится, либо станет нечитаемым нагромождением экранирования — для таких форматов есть специализированные библиотеки. Другая типичная ошибка — забыть про re.search в пользу re.match, который проверяет совпадение только с начала строки, из-за чего кажется, что «регулярка не работает», хотя она просто ищет не там. В практике дня это прямо в критериях: парсинг должен быть построчным (generator, не read() целиком) — тот же принцип экономии памяти, что и в generator'ах дня 108. Именованные группы (?P<timestamp>...) вместо позиционных (...) — не просто удобство: они делают код устойчивым к изменению порядка групп в паттерне и превращают match.groupdict() в готовый словарь с понятными ключами вместо match.group(1), match.group(2), где легко перепутать индексы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: для поиска везде — search, не match; большие файлы — построчно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Генератор mock server.log (1000 строк: timestamp, level, message)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Парсер: извлечь все ERROR с датой через named groups
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Топ-5 часов с наибольшим числом ERROR
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Замена IP-адресов на [REDACTED] в копии лога
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. CLI: python parse_log.py server.log --level ERROR
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сохрани итоговую статистику в reports/error-summary.txt
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Парсинг построчно (memory-efficient)\n- [ ] regex с named groups для timestamp и level\n- [ ] Итоговая статистика в читаемом виде

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Генератор mock server.log (1000 строк: timestamp, level, message)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Парсер: извлечь все ERROR с датой через named groups
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Топ-5 часов с наибольшим числом ERROR
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-16/git commit -m \"week 16 day 111: log parser with regex\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • re.match только с начала строки — для поиска везде re.search
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Жадные квантификаторы .* — неожиданные совпадения
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 112 (Вс): Ревью ООП и алгоритмов

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к CLI Task Manager

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью ООП и алгоритмов готовит к SQLite-проекту недели. SOLID на junior-уровне: Single Responsibility — один класс, одна причина для изменения; Open/Closed — расширяй через композицию, не правь базовый класс везде. Не усложняй: простой скрипт — функции + dataclasses, сложный домен — классы с поведением.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Code smells: god class на 500 строк, дублирование, magic numbers без констант. LeetCode Easy (Two Sum, Valid Parentheses) закрепляет структуры данных вне pet-проекта. Рефакторинг Expense Tracker на Expense + ExpenseStore — мост к TaskRepository.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подготовь venv для недели 17 с psycopg2-binary и python-dotenv. Конспект Big O на одну страницу — пригодится при EXPLAIN и выборе индексов. Тег week-16-done на финальном коммите.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель для ревью-дня: думай о SOLID не как о наборе догм, а как о наборе вопросов-фильтров, которые ты задаёшь коду после того, как он заработал, а не до. «У этого класса одна причина для изменения?» — если нет, скорее всего пора разделить god class на несколько с чёткой ответственностью. Это защита от переусложнения не меньше, чем от недоусложнения: простому CLI-скрипту не нужна абстрактная фабрика, а TaskRepository с несколькими бэкендами хранения — вполне.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это важно дальше: рефакторинг Expense Tracker на Expense + ExpenseStore сегодня — прямая репетиция архитектуры, которую ты повторишь через два дня в SQLite-проекте недели, а затем в разделении models/schemas/crud FastAPI (неделя 18) и routes/controllers/services Express (неделя 19). Умение распознать «этот код стоит разбить на несколько сущностей» — переносимый навык, не привязанный к конкретному фреймворку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение выпускников этого этапа — считать, что больше классов и паттернов автоматически означает более «профессиональный» код; на практике over-engineering (фабрики фабрик для трёх типов объектов) так же вреден, как один файл на 500 строк. LeetCode Easy задачи в практике дня не про запоминание решений, а про распознавание паттернов (хеш-таблица вместо вложенного цикла, два указателя вместо перебора) — тот же навык, что пригодится при выборе структуры данных в реальном проекте, а не абстрактная гимнастика для собеседований. Ревью недели — это ещё и точка перехода: SQLite и sqlite3, с которыми ты работал в проекте, следующая неделя расширит до PostgreSQL и psycopg2, а ООП-приёмы (dataclass, ABC, композиция) станут строительными блоками моделей SQLAlchemy.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: ООП — инструмент, не цель; простые данные — dataclass, сложная логика — классы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реши 3 задачи LeetCode Easy: Two Sum, Valid Parentheses, Merge Sorted Array
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рефакторинг Expense Tracker на классы Expense, ExpenseStore
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. ExpenseStore.save() / load() через pathlib + JSON
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Напиши ответы в notes/oop-review.md: 3 магических метода и зачем
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Конспект Big O на 1 страницу с примерами из недели
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай venv и requirements.txt для недели 17
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] 3 LeetCode задачи приняты\n- [ ] ExpenseStore с save/load через pathlib\n- [ ] Конспект Big O на 1 страницу

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Реши 3 задачи LeetCode Easy: Two Sum, Valid Parentheses, Merge Sorted Array
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Рефакторинг Expense Tracker на классы Expense, ExpenseStore
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. ExpenseStore.save() / load() через pathlib + JSON
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-16/git commit -m \"week 16 day 112: OOP review and LeetCode\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поставь тег: git tag week-16-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CLI Task Manager (SQLite) — расширенная версия с ООП и реляционной БД. Полное описание: docs/projects.md — неделя 16.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Архитектура

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Классы: Task, Tag, TaskRepository (SQLite), TaskCLI (меню и ввод)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Схема БД: tasks, tags, task_tags (many-to-many)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CRUD: создание, список, обновление статуса, удаление, поиск по тегу
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Транзакции: try/except + conn.rollback() при ошибке
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. UI: rich — таблица задач, цвет по статусу (pending / done)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Требования

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • ORM не используем — чистый sqlite3 (SQLAlchemy на нед. 18)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Все SQL с placeholders (?), никогда f-string в запросах
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • schema.sql + seed с 5+ задачами и 3+ тегами
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • README: установка, команды CLI, ER-диаграмма схемы
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • .env не нужен — SQLite локальный файл data/tasks.db
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • python -m task_cli или python main.py запускает интерактивное меню
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поиск и фильтр по статусу и тегу работают
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Many-to-many: задача может иметь несколько тегов
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Транзакция откатывается при нарушении FK
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • README + схема БД + скриншот rich-таблицы
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Тег week-16-done на финальном коммите
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • __init__ vs __new__ — в чём разница (обзор)?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • list.pop(0) — какая сложность и почему?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Когда dataclass, когда полноценный class?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • pathlib vs os.path — что предпочтительнее в 2024+?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как защититься от SQL injection в sqlite3?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **CLI Task Manager** в `learning-log/week-16/`, осмысленная Git-история, тег `week-16-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nPython ООП, SQLite, алгоритмы\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-16-day-106", "label": "День 106 (Пн): Классы и объекты"}, {"id": "week-16-day-107", "label": "День 107 (Вт): Наследование, композиция, dataclasses"}, {"id": "week-16-day-108", "label": "День 108 (Ср): Магические методы и итераторы"}, {"id": "week-16-day-109", "label": "День 109 (Чт): Алгоритмы и Big O"}, {"id": "week-16-day-110", "label": "День 110 (Пт): pathlib и работа с файловой системой"}, {"id": "week-16-day-111", "label": "День 111 (Сб): regex и обработка текстовых логов"}, {"id": "week-16-day-112", "label": "День 112 (Вс): Ревью ООП и алгоритмов"}, {"id": "week-16-project", "label": "Проект недели"}, {"id": "week-16-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-16-review", "label": "Проверь себя"}], "text": "Неделя 16: Python — ООП, алгоритмы, файлы Цель недели: освоить объектно-ориентированный Python, оценку сложности и работу с файловой системой. Литература: Python OOP , Real Python — pathlib , Big-O Cheat Sheet Проект недели: CLI Task Manager (SQLite) — классы Task , TaskRepository , CRUD через sqlite3 , теги many-to-many. Git: папка learning-log/week-16/ , минимум 1 осмысленный коммит в день; к концу недели тег week-16-done . День 106 (Пн): Классы и объекты Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к CLI Task Manager Теория Объектно-ориентированное программирование в Python объединяет данные и поведение в одной сущности — классе. class BankAccount: с методом __init__(self, ...) инициал…"} \ No newline at end of file diff --git a/docs/weeks/17.json b/docs/weeks/17.json index 31776cf..5552b0a 100644 --- a/docs/weeks/17.json +++ b/docs/weeks/17.json @@ -1 +1 @@ -{"id": "week-17", "title": "SQL", "fullTitle": "Неделя 17: SQL, PostgreSQL, индексы", "html": "

                                                                                                                                                                                                                        Неделя 17: SQL, PostgreSQL, индексы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: освоить реляционные БД, SQL-запросы, PostgreSQL и оптимизацию через индексы.\nЛитература: SQLBolt, PostgreSQL Tutorial, Use The Index, Luke\nПроект недели: Library Database — PostgreSQL-схема библиотеки, 15+ запросов, индексы, EXPLAIN.\nGit: папка learning-log/week-17/, SQL-скрипты в schema.sql, seed.sql, queries.sql; тег week-17-done.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 113 (Пн): SQL основы — SELECT, фильтрация, сортировка

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library Database

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        SQL — декларативный язык: ты описываешь, какие данные нужны, а СУБД решает, как их достать. Базовый pipeline: SELECT колонки FROM таблицы WHERE условие ORDER BY сортировка LIMIT ограничение. DISTINCT убирает дубликаты строк в результате.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Операторы фильтрации: =, <>, IN (...), BETWEEN, LIKE 'Py%' (префикс), IS NULL / IS NOT NULL. Агрегаты COUNT, SUM, AVG, MIN, MAX сворачивают множество строк. GROUP BY группирует перед агрегацией; HAVING фильтрует группы после агрегации — не путай с WHERE, который фильтрует строки до.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Порядок выполнения SQL: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT. Понимание этого порядка объясняет, почему нельзя использовать алиас SELECT в WHERE той же фазы. SELECT * удобно в учебе, в production выбирай нужные колонки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: WHERE фильтрует строки, HAVING — группы; SQL описывает результат, не алгоритм.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Установи DB Browser for SQLite или sqlite3 CLI для быстрых экспериментов
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Создай БД «shop»: products, categories, orders с PRIMARY KEY
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. 10+ SELECT-запросов: топ-5 дорогих, средняя цена, count по категории
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Запрос с GROUP BY category_id и HAVING count(*) > 2
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Запрос с DISTINCT и сортировкой по двум колонкам
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сохрани все запросы в queries/day113.sql с комментариями
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Схема с PRIMARY KEY на каждой таблице\n- [ ] ≥ 10 осмысленных запросов в queries.sql\n- [ ] Понимаешь разницу WHERE vs HAVING

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Установи DB Browser for SQLite или sqlite3 CLI для быстрых экспериментов
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Создай БД «shop»: products, categories, orders с PRIMARY KEY
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. 10+ SELECT-запросов: топ-5 дорогих, средняя цена, count по категории
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-17/git commit -m \"week 17 day 113: SQL SELECT and aggregates\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • SELECT * в production — выбирай нужные колонки
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • GROUP BY без агрегата в SELECT — ошибка в строгом SQL
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 114 (Вт): JOIN, INSERT, UPDATE, DELETE

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library Database

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Реляционная модель связывает таблицы ключами. INNER JOIN возвращает только строки с совпадением в обеих таблицах. LEFT JOIN сохраняет все строки «слева» и подставляет NULL справа, если совпадения нет — идеально для «клиенты без заказов» (WHERE orders.id IS NULL).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DML — изменение данных: INSERT, UPDATE, DELETE. Золотое правило: UPDATE и DELETE всегда с осмысленным WHERE. Без WHERE ты изменишь или удалишь всю таблицу — катастрофа, даже в учебной БД. FOREIGN KEY и REFERENCES обеспечивают целостность на уровне СУБД, не только приложения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        ON DELETE CASCADE удаляет дочерние записи вместе с родителем; SET NULL обнуляет FK. Транзакция BEGIN → операции → COMMIT или ROLLBACK — атомарность: либо всё, либо ничего. Забытый ON в JOIN даёт декартово произведение — взрыв числа строк.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: JOIN связывает таблицы; DELETE/UPDATE без WHERE — инцидент.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Расширь shop: customers, order_items с FK
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Запрос: заказы с именами клиентов (INNER JOIN)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Клиенты без заказов (LEFT JOIN + WHERE orders.id IS NULL)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. UPDATE цены категории «sale» −10% в транзакции
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. DELETE тестовых записей с ROLLBACK для проверки
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Запрос «выручка по клиенту» через JOIN + SUM
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] FOREIGN KEY между таблицами\n- [ ] JOIN-запрос возвращает ожидаемые строки\n- [ ] DELETE только с WHERE (не без него!)

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Расширь shop: customers, order_items с FK
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Запрос: заказы с именами клиентов (INNER JOIN)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Клиенты без заказов (LEFT JOIN + WHERE orders.id IS NULL)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-17/git commit -m \"week 17 day 114: JOINs and DML with transactions\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • DELETE/UPDATE без WHERE — катастрофа
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Cartesian product — забытый ON в JOIN
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 115 (Ср): Нормализация и проектирование схемы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library Database

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Нормализация убирает избыточность и аномалии обновления. 1NF — атомарные значения в ячейке (не CSV списка id). 2NF — нет частичных зависимостей от составного ключа. 3NF — нет транзитивных зависимостей (город заёмщика не должен дублироваться в каждой записи loan, если borrower уже хранит город).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        One-to-many: FK в таблице «многих» (books.author_id → authors.id). Many-to-many: junction table (task_tags с двумя FK). Именование: snake_case, plural tables (authors, books) — выбери конвенцию и держись её. CHECK (price > 0) и NOT NULL валидируют на уровне БД.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Денормализация — осознанный trade-off ради скорости чтения, не лень проектировать. ER-диаграмма на dbdiagram.io или Mermaid фиксирует связи до написания SQL. Антипаттерн: хранить список id в одной TEXT-колонке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: нормализация защищает от дублирования; many-to-many — всегда junction table.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Спроектируй БД «Библиотека»: authors, books, borrowers, loans
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. ER-диаграмма на dbdiagram.io или Mermaid в README
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CREATE TABLE с NOT NULL, UNIQUE, CHECK constraints
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Seed: 5 авторов, 20 книг, 3 заёмщика, 10 займов
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Документируй связи: 1:N author→books, N:M если нужны genres
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Проверь: нет дублирования author_name в books
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Нет дублирования author name в books\n- [ ] Junction table для many-to-many (если нужна)\n- [ ] ER-диаграмма в repo

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Спроектируй БД «Библиотека»: authors, books, borrowers, loans
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. ER-диаграмма на dbdiagram.io или Mermaid в README
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CREATE TABLE с NOT NULL, UNIQUE, CHECK constraints
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-17/git commit -m \"week 17 day 115: library schema and ER diagram\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Хранение списка id в одной колонке CSV — антипаттерн
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Nullable всего подряд — потеря целостности данных
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 116 (Чт): PostgreSQL — установка и отличия от SQLite

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library Database

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        PostgreSQL — серверная СУБД для production: concurrent access, роли, extensions, богатые типы (JSONB, UUID, TIMESTAMPTZ). SQLite — один файл, zero-config, идеален для прототипов и встроенных приложений. На этой неделе ты переносишь схему «Библиотека» из SQLite в PG.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Docker: docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=pass postgres:16 поднимает изолированный инстанс за секунды. Клиенты: psql, pgAdmin, DBeaver. Диалектные отличия: AUTOINCREMENT (SQLite) vs SERIAL / GENERATED ALWAYS AS IDENTITY (PostgreSQL).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DATABASE_URL=postgresql://user:pass@localhost:5432/library — стандартная строка подключения для приложений. Документируй пароль в .env.example без реальных значений. Сравни SQLite vs PG письменно: когда файл достаточен, когда нужен сервер.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: PostgreSQL — для multi-user и production; миграция учит диалектные различия.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подними PostgreSQL (Docker или локально)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перенеси схему «Библиотека» в PostgreSQL через schema.sql
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Подключись через psql или DBeaver, выполни \\dt и \\d books
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. seed.sql — вставка тестовых данных
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Сравни SQLite vs PG — запиши 5 пунктов в notes/pg-vs-sqlite.md
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай .env.example с DATABASE_URL=postgresql://user:pass@localhost:5432/library
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Подключение к PG работает\n- [ ] Схема создана через SQL-скрипт schema.sql\n- [ ] Seed script seed.sql выполняется без ошибок

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подними PostgreSQL (Docker или локально)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перенеси схему «Библиотека» в PostgreSQL через schema.sql
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Подключись через psql или DBeaver, выполни \\dt и \\d books
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-17/git commit -m \"week 17 day 116: PostgreSQL setup and schema migration\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Забытый пароль postgres в Docker — документируй в .env.example
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Различия SQL диалектов: AUTOINCREMENT vs SERIAL
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 117 (Пт): Индексы и EXPLAIN ANALYZE

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library Database

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Индекс — структура данных (обычно B-tree), ускоряющая поиск по колонке ценой замедления INSERT/UPDATE. CREATE INDEX idx_books_title ON books(title) помогает WHERE title = '...' и LIKE 'Python%' (префикс), но не LIKE '%python' (leading wildcard).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        EXPLAIN ANALYZE показывает реальный план выполнения: Seq Scan (полный перебор) vs Index Scan (по дереву). Сравни cost, rows, actual time до и после индекса на таблице с 10 000+ строк. Составной индекс (author_id, title) — порядок колонок важен для составных запросов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Use The Index, Luke объясняет, когда индекс помогает, а когда оптимизатор его игнорирует. Индекс на каждую колонку — перебор: каждая запись обновляет все индексы. Документируй замеры в notes/indexes.md — это навык для собеседований.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: индекс — trade-off read vs write; EXPLAIN — единственный честный ответ «почему медленно».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Таблица books с 10 000+ строк (скрипт scripts/generate_books.sql)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. EXPLAIN ANALYZE SELECT * FROM books WHERE title LIKE 'Python%' — без индекса
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CREATE INDEX idx_books_title ON books(title)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Повтори EXPLAIN — сравни cost, rows, actual time
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Запиши выводы в notes/indexes.md с скриншотами или копией планов
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Эксперимент: индекс на (author_id) для JOIN-запроса
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Индекс создан на колонке поиска\n- [ ] EXPLAIN показывает Index Scan (или объясни почему Seq Scan)\n- [ ] Записаны выводы в notes/indexes.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Таблица books с 10 000+ строк (скрипт scripts/generate_books.sql)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. EXPLAIN ANALYZE SELECT * FROM books WHERE title LIKE 'Python%' — без индекса
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CREATE INDEX idx_books_title ON books(title)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-17/git commit -m \"week 17 day 117: indexes and EXPLAIN ANALYZE\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Индекс на каждую колонку — замедляет INSERT/UPDATE
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • LIKE '%python' — индекс B-tree не поможет (leading wildcard)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 118 (Сб): SQLite/PostgreSQL из Python

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library Database

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Приложение общается с БД через драйвер. Встроенный sqlite3 использует placeholders ?; psycopg2 / psycopg3 для PostgreSQL — %s. Никогда не вставляй пользовательский ввод в SQL через f-string — это SQL injection. Только параметризованные запросы: cursor.execute('SELECT * FROM books WHERE id = %s', (book_id,)).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Context manager with conn: коммитит при успехе и откатывает при исключении. DATABASE_URL из .env через python-dotenv — 12-factor config. Connection pool (в веб-приложении) переиспользует соединения под нагрузкой; в CLI достаточно одного подключения на операцию.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Абстракция репозитория с методами fetch_all, execute позволяет переключать SQLite и PostgreSQL флагом --db. Скрипт миграции sqlite → postgres учит переносу данных между СУБД. Забытый conn.commit() — изменения не сохранятся.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: placeholders — не опция, а требование безопасности; commit явный или через context manager.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Расширь CLI Task Manager (нед.16): опция --db postgres vs sqlite
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. DATABASE_URL из .env через python-dotenv
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Репозиторий с методами fetch_all, execute для обеих БД
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Скрипт миграции sqlite → postgres (migrate_to_pg.py)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. 3 операции в library_cli.py: список книг, добавить заём, вернуть книгу
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Все запросы — только placeholders
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Нет SQL injection — только placeholders\n- [ ] with conn: или try/finally close\n- [ ] .env.example с DATABASE_URL

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Расширь CLI Task Manager (нед.16): опция --db postgres vs sqlite
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. DATABASE_URL из .env через python-dotenv
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Репозиторий с методами fetch_all, execute для обеих БД
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-17/git commit -m \"week 17 day 118: Python psycopg2 library CLI\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • f-string в SQL: f\"SELECT * FROM users WHERE name = '{name}'\" — injection
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Забытый conn.commit() — изменения не сохраняются
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 119 (Вс): Ревью SQL и подготовка к ORM

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~25м теория · ~2.5ч практика · ~10м Git · ~40м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~15м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library Database

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью SQL закрепляет фундамент перед ORM на неделе 18. ACID: Atomicity (всё или ничего), Consistency (инварианты БД), Isolation (параллельные транзакции не мешают), Durability (commit переживает сбой). Транзакции — не абстракция, а гарантия при переводе денег или выдаче книги.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Views — сохранённые запросы; stored procedures — логика внутри БД (обзор). Isolation levels (read committed, serializable) влияют на фантомные чтения — на junior достаточно знать, что они существуют. SQL Style Guide делает запросы читаемыми для команды.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        ORM (SQLAlchemy) маппит таблицы на классы Python: меньше boilerplate SQL, но риск N+1 и «магических» запросов. Понимание raw SQL остаётся обязательным для отладки и оптимизации. Установи sqlalchemy fastapi uvicorn в venv — старт недели 18.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: SQL — база; ORM — удобство поверх, не замена понимания JOIN и индексов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди 15 уроков SQLBolt без подсказок — отметь слабые темы
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Напиши 5 сложных запросов: JOIN + агрегат + HAVING + ORDER BY
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Ответь письменно: «INNER vs LEFT JOIN» с примерами из библиотеки
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Запрос «кто не вернул книгу» — просроченные loans
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Установи pip install sqlalchemy fastapi uvicorn в venv
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Финализируй queries.sql — 15+ запросов для проекта
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] 5 сложных запросов с JOIN и агрегатами\n- [ ] Ответы на «INNER vs LEFT JOIN» письменно\n- [ ] venv готов для недели 18

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди 15 уроков SQLBolt без подсказок — отметь слабые темы
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Напиши 5 сложных запросов: JOIN + агрегат + HAVING + ORDER BY
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Ответь письменно: «INNER vs LEFT JOIN» с примерами из библиотеки
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-17/git commit -m \"week 17 day 119: SQL review and 15 queries\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поставь тег: git tag week-17-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        База «Библиотека» — полный SQL-проект на PostgreSQL. Спецификация: docs/projects.md — неделя 17.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура репозитория

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        week-17/\n├── schema.sql          # CREATE TABLE, FK, constraints\n├── seed.sql            # тестовые данные\n├── queries.sql         # 15+ запросов с комментариями\n├── notes/\n│   └── indexes.md      # EXPLAIN до/после\n├── scripts/\n│   └── generate_books.sql\n├── library_cli.py      # 3+ операции через psycopg2\n├── er-diagram.png      # или Mermaid в README\n└── README.md\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Таблицы: authors, books, borrowers, loans с FK и CHECK
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Запросы: топ авторов, просроченные займы, книги без займов, статистика
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Индекс на books.title — EXPLAIN до и после с замерами
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Python CLI: подключение, 3 операции, параметризованные запросы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. docker-compose только для postgres (опционально, пригодится на нед. 21)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • FK constraints работают — нельзя удалить автора с книгами без CASCADE
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Запрос «кто не вернул книгу» корректен и документирован
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Индекс документирован с цифрами из EXPLAIN ANALYZE
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • queries.sql содержит ≥ 15 осмысленных запросов
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • README: как поднять PG, выполнить schema/seed, запустить CLI
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Тег week-17-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • INNER JOIN vs LEFT JOIN — пример каждого?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Зачем PRIMARY KEY и FOREIGN KEY?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что показывает EXPLAIN ANALYZE?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как защититься от SQL injection?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • PostgreSQL vs SQLite — 3 случая когда PG?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Library Database** в `learning-log/week-17/`, осмысленная Git-история, тег `week-17-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nSQL и PostgreSQL на практике\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-17-day-113", "label": "День 113 (Пн): SQL основы — SELECT, фильтрация, сортировка"}, {"id": "week-17-day-114", "label": "День 114 (Вт): JOIN, INSERT, UPDATE, DELETE"}, {"id": "week-17-day-115", "label": "День 115 (Ср): Нормализация и проектирование схемы"}, {"id": "week-17-day-116", "label": "День 116 (Чт): PostgreSQL — установка и отличия от SQLite"}, {"id": "week-17-day-117", "label": "День 117 (Пт): Индексы и EXPLAIN ANALYZE"}, {"id": "week-17-day-118", "label": "День 118 (Сб): SQLite/PostgreSQL из Python"}, {"id": "week-17-day-119", "label": "День 119 (Вс): Ревью SQL и подготовка к ORM"}, {"id": "week-17-project", "label": "Проект недели"}, {"id": "week-17-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-17-review", "label": "Проверь себя"}], "text": "Неделя 17: SQL, PostgreSQL, индексы Цель недели: освоить реляционные БД, SQL-запросы, PostgreSQL и оптимизацию через индексы. Литература: SQLBolt , PostgreSQL Tutorial , Use The Index, Luke Проект недели: Library Database — PostgreSQL-схема библиотеки, 15+ запросов, индексы, EXPLAIN. Git: папка learning-log/week-17/ , SQL-скрипты в schema.sql , seed.sql , queries.sql ; тег week-17-done . День 113 (Пн): SQL основы — SELECT, фильтрация, сортировка Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Library Database Теория SQL — декларативный язык: ты описываешь, какие данные нужны, а СУБД решает, как их достать. Базовый pipeline: SELECT колонки FROM таблицы WHERE условие ORDER BY сортировка LIM…"} \ No newline at end of file +{"id": "week-17", "title": "SQL", "fullTitle": "Неделя 17: SQL, PostgreSQL, индексы", "html": "

                                                                                                                                                                                                                        Неделя 17: SQL, PostgreSQL, индексы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: освоить реляционные БД, SQL-запросы, PostgreSQL и оптимизацию через индексы.\nЛитература: SQLBolt, PostgreSQL Tutorial, Use The Index, Luke\nПроект недели: Library Database — PostgreSQL-схема библиотеки, 15+ запросов, индексы, EXPLAIN.\nGit: папка learning-log/week-17/, SQL-скрипты в schema.sql, seed.sql, queries.sql; тег week-17-done.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 113 (Пн): SQL основы — SELECT, фильтрация, сортировка

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library Database

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        SQL — декларативный язык: ты описываешь, какие данные нужны, а СУБД решает, как их достать. Базовый pipeline: SELECT колонки FROM таблицы WHERE условие ORDER BY сортировка LIMIT ограничение. DISTINCT убирает дубликаты строк в результате.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Операторы фильтрации: =, <>, IN (...), BETWEEN, LIKE 'Py%' (префикс), IS NULL / IS NOT NULL. Агрегаты COUNT, SUM, AVG, MIN, MAX сворачивают множество строк. GROUP BY группирует перед агрегацией; HAVING фильтрует группы после агрегации — не путай с WHERE, который фильтрует строки до.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Порядок выполнения SQL: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT. Понимание этого порядка объясняет, почему нельзя использовать алиас SELECT в WHERE той же фазы. SELECT * удобно в учебе, в production выбирай нужные колонки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: SQL декларативен, как заказ в ресторане — ты говоришь официанту «стейк средней прожарки», а не диктуешь повару пошаговый рецепт с температурой сковороды. СУБД (query planner) сама решает, каким путём достать данные — через полный перебор или индекс, в каком порядке соединить таблицы. Именно поэтому один и тот же SQL-запрос может выполняться по-разному в зависимости от статистики таблиц, а твоя задача — описать что нужно, а не как это получить.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это станет фундаментом всего backend: когда через две недели ты напишешь select(Book).where(Book.title.ilike('%python%')) в SQLAlchemy, под капотом сгенерируется ровно такой же SELECT ... WHERE ... ILIKE, который ты пишешь сегодня руками. Без понимания сырого SQL отладка «странного» ORM-запроса превращается в гадание, а с ним — в чтение сгенерированного SQL и логичный вывод, почему он медленный или неверный.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — пытаться отфильтровать результат агрегации через WHERE: WHERE COUNT(*) > 2 вызовет ошибку, потому что на момент выполнения WHERE агрегаты ещё не посчитаны — для этого существует HAVING, которая работает уже после GROUP BY. Вторая типичная ошибка начинающих — забыть, что колонка, добавленная в SELECT без агрегатной функции, должна присутствовать и в GROUP BY, иначе строгий SQL-режим (в PostgreSQL это стандартное поведение) выдаст ошибку «column must appear in GROUP BY clause». Практика дня с HAVING count(*) > 2 — это ровно тренировка на понимание порядка выполнения, а не запоминание синтаксиса.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: WHERE фильтрует строки, HAVING — группы; SQL описывает результат, не алгоритм.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Установи DB Browser for SQLite или sqlite3 CLI для быстрых экспериментов
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Создай БД «shop»: products, categories, orders с PRIMARY KEY
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. 10+ SELECT-запросов: топ-5 дорогих, средняя цена, count по категории
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Запрос с GROUP BY category_id и HAVING count(*) > 2
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Запрос с DISTINCT и сортировкой по двум колонкам
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сохрани все запросы в queries/day113.sql с комментариями
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Схема с PRIMARY KEY на каждой таблице\n- [ ] ≥ 10 осмысленных запросов в queries.sql\n- [ ] Понимаешь разницу WHERE vs HAVING

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Установи DB Browser for SQLite или sqlite3 CLI для быстрых экспериментов
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Создай БД «shop»: products, categories, orders с PRIMARY KEY
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. 10+ SELECT-запросов: топ-5 дорогих, средняя цена, count по категории
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-17/git commit -m \"week 17 day 113: SQL SELECT and aggregates\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • SELECT * в production — выбирай нужные колонки
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • GROUP BY без агрегата в SELECT — ошибка в строгом SQL
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 114 (Вт): JOIN, INSERT, UPDATE, DELETE

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library Database

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Реляционная модель связывает таблицы ключами. INNER JOIN возвращает только строки с совпадением в обеих таблицах. LEFT JOIN сохраняет все строки «слева» и подставляет NULL справа, если совпадения нет — идеально для «клиенты без заказов» (WHERE orders.id IS NULL).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DML — изменение данных: INSERT, UPDATE, DELETE. Золотое правило: UPDATE и DELETE всегда с осмысленным WHERE. Без WHERE ты изменишь или удалишь всю таблицу — катастрофа, даже в учебной БД. FOREIGN KEY и REFERENCES обеспечивают целостность на уровне СУБД, не только приложения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        ON DELETE CASCADE удаляет дочерние записи вместе с родителем; SET NULL обнуляет FK. Транзакция BEGIN → операции → COMMIT или ROLLBACK — атомарность: либо всё, либо ничего. Забытый ON в JOIN даёт декартово произведение — взрыв числа строк.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель для JOIN — диаграмма Венна из двух пересекающихся кругов. INNER JOIN — это только пересечение (строки, у которых есть пара в обеих таблицах); LEFT JOIN — весь левый круг целиком плюс то, что попало в пересечение, а недостающая часть справа заполняется NULL. Именно поэтому «клиенты без заказов» находятся через LEFT JOIN ... WHERE orders.id IS NULL: NULL в правой части и есть признак отсутствия совпадения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это фундамент, который прорастёт в обе следующие недели: relationship() в SQLAlchemy (неделя 18) под капотом генерирует ровно такой же JOIN, когда ты обращаешься к author.books, а понимание ON DELETE CASCADE, которое ты настраиваешь сегодня, определяет, будут ли реальные пользовательские данные корректно удаляться или зависать сиротами при удалении родительской записи в продакшене.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое и самое опасное заблуждение — думать, что DELETE FROM orders WHERE customer_id = 5 «удалит только пять заказов», забыв, что без WHERE DELETE FROM orders стирает все строки таблицы безвозвратно, и в отличие от файла это не попадёт в корзину. Именно поэтому в критериях дня явно требуется тестировать деструктивные операции через BEGIN + ROLLBACK, прежде чем выполнять их «по-настоящему»: привычка проверять запрос в транзакции с откатом — это тот самый навык, который убережёт от инцидента на реальной базе данных. Такая же осторожность нужна и с самим JOIN: забытое условие ON превращает соединение в декартово произведение, где каждая строка левой таблицы умножается на каждую строку правой — на таблицах в тысячи строк результат может незаметно взорваться до миллионов, съедая память и время.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: JOIN связывает таблицы; DELETE/UPDATE без WHERE — инцидент.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Расширь shop: customers, order_items с FK
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Запрос: заказы с именами клиентов (INNER JOIN)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Клиенты без заказов (LEFT JOIN + WHERE orders.id IS NULL)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. UPDATE цены категории «sale» −10% в транзакции
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. DELETE тестовых записей с ROLLBACK для проверки
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Запрос «выручка по клиенту» через JOIN + SUM
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] FOREIGN KEY между таблицами\n- [ ] JOIN-запрос возвращает ожидаемые строки\n- [ ] DELETE только с WHERE (не без него!)

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Расширь shop: customers, order_items с FK
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Запрос: заказы с именами клиентов (INNER JOIN)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Клиенты без заказов (LEFT JOIN + WHERE orders.id IS NULL)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-17/git commit -m \"week 17 day 114: JOINs and DML with transactions\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • DELETE/UPDATE без WHERE — катастрофа
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Cartesian product — забытый ON в JOIN
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 115 (Ср): Нормализация и проектирование схемы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library Database

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Нормализация убирает избыточность и аномалии обновления. 1NF — атомарные значения в ячейке (не CSV списка id). 2NF — нет частичных зависимостей от составного ключа. 3NF — нет транзитивных зависимостей (город заёмщика не должен дублироваться в каждой записи loan, если borrower уже хранит город).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        One-to-many: FK в таблице «многих» (books.author_id → authors.id). Many-to-many: junction table (task_tags с двумя FK). Именование: snake_case, plural tables (authors, books) — выбери конвенцию и держись её. CHECK (price > 0) и NOT NULL валидируют на уровне БД.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Денормализация — осознанный trade-off ради скорости чтения, не лень проектировать. ER-диаграмма на dbdiagram.io или Mermaid фиксирует связи до написания SQL. Антипаттерн: хранить список id в одной TEXT-колонке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель нормализации — аккуратная картотека, где каждый факт хранится ровно в одном месте. Если город заёмщика продублирован в каждой записи loan, изменение города потребует найти и поправить десятки строк, а забытая хотя бы одна — уже аномалия обновления (данные противоречат друг другу). Нормализованная схема устраняет саму возможность такого рассинхрона: город хранится один раз в borrowers, и loans лишь ссылается на него по FK.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Схема «Библиотека», которую ты проектируешь сегодня, — не разовое упражнение: это буквально та же схема authors/books/borrowers/loans, которую ты перенесёшь в SQLAlchemy-модели на неделе 18 и в schema.sql для Express на неделе 19. Ошибка в проектировании здесь (например, отсутствие junction table для many-to-many) аукнется трижды — придётся переделывать модели во всех трёх проектах.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — доводить нормализацию до абсурда, разбивая всё на мельчайшие таблицы там, где осознанная денормализация была бы разумным компромиссом ради скорости чтения (это решение, а не лень). Куда более частая ошибка новичков — обратная: хранить список связанных id одной строкой через запятую в TEXT-колонке вместо junction table, что делает невозможными нормальные JOIN-запросы и проверку целостности через FK. В практике дня это прямо проверяется: если книге нужно несколько жанров, единственный правильный путь — таблица book_genres с двумя внешними ключами, а не текстовое поле. Отдельно стоит проговорить конвенции именования: snake_case, множественное число для таблиц (authors, а не author) — мелочь, которая экономит часы споров в команде и делает схему предсказуемой для любого, кто открывает её впервые.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: нормализация защищает от дублирования; many-to-many — всегда junction table.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Спроектируй БД «Библиотека»: authors, books, borrowers, loans
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. ER-диаграмма на dbdiagram.io или Mermaid в README
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CREATE TABLE с NOT NULL, UNIQUE, CHECK constraints
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Seed: 5 авторов, 20 книг, 3 заёмщика, 10 займов
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Документируй связи: 1:N author→books, N:M если нужны genres
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Проверь: нет дублирования author_name в books
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Нет дублирования author name в books\n- [ ] Junction table для many-to-many (если нужна)\n- [ ] ER-диаграмма в repo

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Спроектируй БД «Библиотека»: authors, books, borrowers, loans
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. ER-диаграмма на dbdiagram.io или Mermaid в README
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CREATE TABLE с NOT NULL, UNIQUE, CHECK constraints
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-17/git commit -m \"week 17 day 115: library schema and ER diagram\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Хранение списка id в одной колонке CSV — антипаттерн
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Nullable всего подряд — потеря целостности данных
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 116 (Чт): PostgreSQL — установка и отличия от SQLite

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library Database

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        PostgreSQL — серверная СУБД для production: concurrent access, роли, extensions, богатые типы (JSONB, UUID, TIMESTAMPTZ). SQLite — один файл, zero-config, идеален для прототипов и встроенных приложений. На этой неделе ты переносишь схему «Библиотека» из SQLite в PG.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Docker: docker run -d -p 5432:5432 -e POSTGRES_PASSWORD=pass postgres:16 поднимает изолированный инстанс за секунды. Клиенты: psql, pgAdmin, DBeaver — psql быстрее для точечных запросов и скриптов, GUI-клиенты удобнее для визуального просмотра схемы. Диалектные отличия: AUTOINCREMENT (SQLite) vs SERIAL / GENERATED ALWAYS AS IDENTITY (PostgreSQL).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DATABASE_URL=postgresql://user:pass@localhost:5432/library — стандартная строка подключения для приложений. Документируй пароль в .env.example без реальных значений. Сравни SQLite vs PG письменно: когда файл достаточен, когда нужен сервер.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: SQLite — это личный блокнот-файл, лежащий рядом с программой (embedded, без сети, один процесс пишет за раз); PostgreSQL — это офисный сервер базы данных, к которому по сети одновременно подключаются десятки клиентов через клиент-серверный протокол. Отсюда и разница use case: прототип, CLI-утилита, мобильное приложение — SQLite; веб-сервис с конкурентным доступом — PostgreSQL.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Эта миграция — не разовое упражнение: практически каждый проект, который ты соберёшь дальше в программе (FastAPI на неделе 18, Express на неделе 19, деплой на неделе 21), будет подключаться именно к PostgreSQL через одну и ту же переменную DATABASE_URL — сегодняшняя настройка Docker-контейнера и строки подключения используется без изменений ещё как минимум трижды.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать SQL PostgreSQL и SQLite полностью взаимозаменяемым диалектом: AUTOINCREMENT в SQLite становится SERIAL или GENERATED ALWAYS AS IDENTITY в PostgreSQL, типы данных богаче (JSONB, UUID, TIMESTAMPTZ не имеют прямых аналогов в SQLite), а поведение constraint-ов местами строже. В практике дня перенос схемы «Библиотека» специально выявляет эти расхождения — их стоит зафиксировать письменно в notes/pg-vs-sqlite.md, чтобы не наступать на те же грабли в будущих проектах. Ещё один момент, который легко упустить: SQLite не требует отдельного процесса-сервера и пароля, а PostgreSQL требует явного управления доступом (роли, пароли, сетевые порты) — именно поэтому сегодняшняя настройка .env.example с DATABASE_URL без реальных секретов в самом репозитории становится обязательной привычкой на все оставшиеся недели курса. Полезно письменно зафиксировать и обратное: в каких случаях SQLite достаточно даже для боевого использования — например, мобильные и десктопные приложения, локальные кэши или сервисы с одним писателем и низкой конкурентной нагрузкой, где сетевой сервер был бы избыточен.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: PostgreSQL — для multi-user и production; миграция учит диалектные различия.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подними PostgreSQL (Docker или локально)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перенеси схему «Библиотека» в PostgreSQL через schema.sql
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Подключись через psql или DBeaver, выполни \\dt и \\d books
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. seed.sql — вставка тестовых данных
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Сравни SQLite vs PG — запиши 5 пунктов в notes/pg-vs-sqlite.md
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Создай .env.example с DATABASE_URL=postgresql://user:pass@localhost:5432/library
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Подключение к PG работает\n- [ ] Схема создана через SQL-скрипт schema.sql\n- [ ] Seed script seed.sql выполняется без ошибок

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подними PostgreSQL (Docker или локально)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Перенеси схему «Библиотека» в PostgreSQL через schema.sql
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Подключись через psql или DBeaver, выполни \\dt и \\d books
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-17/git commit -m \"week 17 day 116: PostgreSQL setup and schema migration\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Забытый пароль postgres в Docker — документируй в .env.example
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Различия SQL диалектов: AUTOINCREMENT vs SERIAL
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 117 (Пт): Индексы и EXPLAIN ANALYZE

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library Database

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Индекс — структура данных (обычно B-tree), ускоряющая поиск по колонке ценой замедления INSERT/UPDATE. CREATE INDEX idx_books_title ON books(title) помогает WHERE title = '...' и LIKE 'Python%' (префикс), но не LIKE '%python' (leading wildcard).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        EXPLAIN ANALYZE показывает реальный план выполнения: Seq Scan (полный перебор) vs Index Scan (по дереву). Сравни cost, rows, actual time до и после индекса на таблице с 10 000+ строк. Составной индекс (author_id, title) — порядок колонок важен для составных запросов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Use The Index, Luke объясняет, когда индекс помогает, а когда оптимизатор его игнорирует. Индекс на каждую колонку — перебор: каждая запись обновляет все индексы. Документируй замеры в notes/indexes.md — это навык для собеседований.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: индекс — это алфавитный указатель в конце книги. Без него, чтобы найти все упоминания слова, придётся пролистать каждую страницу (Seq Scan, O(n)); с указателем ты сразу открываешь нужную страницу (Index Scan, ближе к O(log n)) — та самая разница между линейным и логарифмическим ростом, которую ты изучал на неделе 16 в контексте Big O, здесь материализуется в конкретных миллисекундах.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это — один из главных практических навыков backend-разработчика: медленный endpoint в проекте FastAPI (неделя 18) почти всегда диагностируется и чинится именно этим приёмом — EXPLAIN ANALYZE показывает, какой шаг запроса «съедает» время, а индекс на нужной колонке превращает Seq Scan в Index Scan. Собеседования на backend-позиции регулярно спрашивают именно про это: «как найти и ускорить медленный запрос».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что «индекс всегда ускоряет чтение, значит стоит поставить его на каждую колонку». На самом деле у индекса есть цена: каждая вставка, обновление или удаление строки должна обновить все индексы таблицы, что замедляет запись и увеличивает размер БД на диске. Кроме того, оптимизатор PostgreSQL может проигнорировать индекс на маленькой таблице или при низкой селективности колонки (например, поле status с тремя значениями на миллион строк), потому что полный перебор иногда дешевле навигации по дереву. Именно поэтому критерий практики требует не просто создать индекс, а сравнить EXPLAIN ANALYZE до и после цифрами, а не полагаться на интуицию.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: индекс — trade-off read vs write; EXPLAIN — единственный честный ответ «почему медленно».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Таблица books с 10 000+ строк (скрипт scripts/generate_books.sql)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. EXPLAIN ANALYZE SELECT * FROM books WHERE title LIKE 'Python%' — без индекса
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CREATE INDEX idx_books_title ON books(title)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Повтори EXPLAIN — сравни cost, rows, actual time
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Запиши выводы в notes/indexes.md с скриншотами или копией планов
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Эксперимент: индекс на (author_id) для JOIN-запроса
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Индекс создан на колонке поиска\n- [ ] EXPLAIN показывает Index Scan (или объясни почему Seq Scan)\n- [ ] Записаны выводы в notes/indexes.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Таблица books с 10 000+ строк (скрипт scripts/generate_books.sql)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. EXPLAIN ANALYZE SELECT * FROM books WHERE title LIKE 'Python%' — без индекса
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CREATE INDEX idx_books_title ON books(title)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-17/git commit -m \"week 17 day 117: indexes and EXPLAIN ANALYZE\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Индекс на каждую колонку — замедляет INSERT/UPDATE
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • LIKE '%python' — индекс B-tree не поможет (leading wildcard)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 118 (Сб): SQLite/PostgreSQL из Python

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library Database

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Приложение общается с БД через драйвер. Встроенный sqlite3 использует placeholders ?; psycopg2 / psycopg3 для PostgreSQL — %s. Никогда не вставляй пользовательский ввод в SQL через f-string — это SQL injection. Только параметризованные запросы: cursor.execute('SELECT * FROM books WHERE id = %s', (book_id,)).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Context manager with conn: коммитит при успехе и откатывает при исключении. DATABASE_URL из .env через python-dotenv — 12-factor config. Connection pool (в веб-приложении) переиспользует соединения под нагрузкой; в CLI достаточно одного подключения на операцию.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Абстракция репозитория с методами fetch_all, execute позволяет переключать SQLite и PostgreSQL флагом --db. Скрипт миграции sqlite → postgres учит переносу данных между СУБД. Забытый conn.commit() — изменения не сохранятся.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: плейсхолдер (? или %s) — это форма с чётко заданными полями для заполнения, которую драйвер сначала отправляет в СУБД как шаблон, а данные передаёт отдельно как значения. СУБД никогда не интерпретирует значения как код — в отличие от f-строки, где пользовательский ввод буквально дописывается в текст SQL-запроса, и злоумышленник может вставить туда '; DROP TABLE users; -- вместо ожидаемого имени.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Абстракция репозитория, которую ты пишешь сегодня (fetch_all, execute с переключением --db), — не учебная условность: это прямой предшественник паттерна Repository/CRUD-слоя в SQLAlchemy на неделе 18 и Pool.query() в Express на неделе 19 — везде задача одна и та же: изолировать SQL от бизнес-логики и гарантировать безопасные параметризованные запросы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что with conn: в психопг2 закрывает и само соединение: на самом деле контекстный менеджер отвечает только за транзакцию — коммитит при успешном выходе или откатывает при исключении, но соединение остаётся открытым и должно быть закрыто отдельно (conn.close() или отдельный with). Вторая типичная ошибка — забыть conn.commit() при работе без контекстного менеджера: запрос выполнится, SELECT после него в той же сессии покажет изменения, но после перезапуска приложения данные окажутся «потерянными», потому что физически не были записаны на диск. Полезная привычка на будущее: заворачивать операции записи в with conn: или явный try/except/finally с rollback() в случае ошибки — тот же паттерн, который через несколько дней превратится в session SQLAlchemy с автоматическим управлением транзакцией на уровне ORM.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: placeholders — не опция, а требование безопасности; commit явный или через context manager.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Расширь CLI Task Manager (нед.16): опция --db postgres vs sqlite
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. DATABASE_URL из .env через python-dotenv
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Репозиторий с методами fetch_all, execute для обеих БД
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Скрипт миграции sqlite → postgres (migrate_to_pg.py)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. 3 операции в library_cli.py: список книг, добавить заём, вернуть книгу
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Все запросы — только placeholders
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Нет SQL injection — только placeholders\n- [ ] with conn: или try/finally close\n- [ ] .env.example с DATABASE_URL

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Расширь CLI Task Manager (нед.16): опция --db postgres vs sqlite
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. DATABASE_URL из .env через python-dotenv
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Репозиторий с методами fetch_all, execute для обеих БД
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-17/git commit -m \"week 17 day 118: Python psycopg2 library CLI\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • f-string в SQL: f\"SELECT * FROM users WHERE name = '{name}'\" — injection
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Забытый conn.commit() — изменения не сохраняются
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 119 (Вс): Ревью SQL и подготовка к ORM

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~2.5ч практика · ~10м Git · ~40м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library Database

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью SQL закрепляет фундамент перед ORM на неделе 18. ACID: Atomicity (всё или ничего), Consistency (инварианты БД), Isolation (параллельные транзакции не мешают), Durability (commit переживает сбой). Транзакции — не абстракция, а гарантия при переводе денег или выдаче книги.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Views — сохранённые запросы; stored procedures — логика внутри БД (обзор). Isolation levels (read committed, serializable) влияют на фантомные чтения — на junior достаточно знать, что они существуют. SQL Style Guide делает запросы читаемыми для команды.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        ORM (SQLAlchemy) маппит таблицы на классы Python: меньше boilerplate SQL, но риск N+1 и «магических» запросов. Понимание raw SQL остаётся обязательным для отладки и оптимизации. Установи sqlalchemy fastapi uvicorn в venv — старт недели 18.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель ACID — это четыре независимых обещания, которые транзакция даёт тебе как разработчику, и их стоит держать в голове как чек-лист перед любой операцией с деньгами или запасами: Atomicity — операция либо выполнится целиком, либо не выполнится вовсе, без промежуточного «наполовину»; Consistency — база данных переходит из одного валидного состояния в другое, не нарушая constraints; Isolation — параллельные транзакции не видят «грязных» промежуточных изменений друг друга; Durability — после commit данные переживут даже сбой питания.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это не абстракция ради экзамена: session.commit() / session.rollback() в SQLAlchemy (неделя 18) и pool.query('COMMIT') в Express (неделя 19) опираются ровно на эти же гарантии — ORM не отменяет необходимости понимать ACID, а лишь делает транзакционную границу менее заметной в коде, из-за чего баги «забыл закоммитить» или «два запроса пересеклись» стали чаще, а не реже.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение выпускников этой недели — думать, что после перехода на ORM сырой SQL больше не понадобится. На практике чтение EXPLAIN-плана, отладка неожиданно медленного ORM-запроса или написание сложной агрегации, которую ORM выразить неудобно, — всё это требует свободного владения SQL, которое ты наработал за эту неделю. Финализация queries.sql с 15+ запросами в практике дня — это не формальность для проекта, а последняя проверка того, что фундамент действительно прочный перед тем, как он будет частично скрыт слоем абстракции. Views и stored procedures стоит знать хотя бы на уровне «это существует и для чего»: view — это именованный сохранённый запрос, который можно использовать как обычную таблицу для чтения, а stored procedure переносит часть логики внутрь самой СУБД — оба инструмента встречаются в legacy-системах, и способность их прочитать пригодится раньше, чем способность написать с нуля.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: SQL — база; ORM — удобство поверх, не замена понимания JOIN и индексов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди 15 уроков SQLBolt без подсказок — отметь слабые темы
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Напиши 5 сложных запросов: JOIN + агрегат + HAVING + ORDER BY
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Ответь письменно: «INNER vs LEFT JOIN» с примерами из библиотеки
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Запрос «кто не вернул книгу» — просроченные loans
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Установи pip install sqlalchemy fastapi uvicorn в venv
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Финализируй queries.sql — 15+ запросов для проекта
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] 5 сложных запросов с JOIN и агрегатами\n- [ ] Ответы на «INNER vs LEFT JOIN» письменно\n- [ ] venv готов для недели 18

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Пройди 15 уроков SQLBolt без подсказок — отметь слабые темы
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Напиши 5 сложных запросов: JOIN + агрегат + HAVING + ORDER BY
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Ответь письменно: «INNER vs LEFT JOIN» с примерами из библиотеки
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-17/git commit -m \"week 17 day 119: SQL review and 15 queries\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поставь тег: git tag week-17-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        База «Библиотека» — полный SQL-проект на PostgreSQL. Спецификация: docs/projects.md — неделя 17.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура репозитория

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        week-17/\n├── schema.sql          # CREATE TABLE, FK, constraints\n├── seed.sql            # тестовые данные\n├── queries.sql         # 15+ запросов с комментариями\n├── notes/\n│   └── indexes.md      # EXPLAIN до/после\n├── scripts/\n│   └── generate_books.sql\n├── library_cli.py      # 3+ операции через psycopg2\n├── er-diagram.png      # или Mermaid в README\n└── README.md\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Таблицы: authors, books, borrowers, loans с FK и CHECK
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Запросы: топ авторов, просроченные займы, книги без займов, статистика
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Индекс на books.title — EXPLAIN до и после с замерами
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Python CLI: подключение, 3 операции, параметризованные запросы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. docker-compose только для postgres (опционально, пригодится на нед. 21)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • FK constraints работают — нельзя удалить автора с книгами без CASCADE
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Запрос «кто не вернул книгу» корректен и документирован
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Индекс документирован с цифрами из EXPLAIN ANALYZE
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • queries.sql содержит ≥ 15 осмысленных запросов
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • README: как поднять PG, выполнить schema/seed, запустить CLI
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Тег week-17-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • INNER JOIN vs LEFT JOIN — пример каждого?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Зачем PRIMARY KEY и FOREIGN KEY?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что показывает EXPLAIN ANALYZE?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как защититься от SQL injection?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • PostgreSQL vs SQLite — 3 случая когда PG?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Library Database** в `learning-log/week-17/`, осмысленная Git-история, тег `week-17-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nSQL и PostgreSQL на практике\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-17-day-113", "label": "День 113 (Пн): SQL основы — SELECT, фильтрация, сортировка"}, {"id": "week-17-day-114", "label": "День 114 (Вт): JOIN, INSERT, UPDATE, DELETE"}, {"id": "week-17-day-115", "label": "День 115 (Ср): Нормализация и проектирование схемы"}, {"id": "week-17-day-116", "label": "День 116 (Чт): PostgreSQL — установка и отличия от SQLite"}, {"id": "week-17-day-117", "label": "День 117 (Пт): Индексы и EXPLAIN ANALYZE"}, {"id": "week-17-day-118", "label": "День 118 (Сб): SQLite/PostgreSQL из Python"}, {"id": "week-17-day-119", "label": "День 119 (Вс): Ревью SQL и подготовка к ORM"}, {"id": "week-17-project", "label": "Проект недели"}, {"id": "week-17-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-17-review", "label": "Проверь себя"}], "text": "Неделя 17: SQL, PostgreSQL, индексы Цель недели: освоить реляционные БД, SQL-запросы, PostgreSQL и оптимизацию через индексы. Литература: SQLBolt , PostgreSQL Tutorial , Use The Index, Luke Проект недели: Library Database — PostgreSQL-схема библиотеки, 15+ запросов, индексы, EXPLAIN. Git: папка learning-log/week-17/ , SQL-скрипты в schema.sql , seed.sql , queries.sql ; тег week-17-done . День 113 (Пн): SQL основы — SELECT, фильтрация, сортировка Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Library Database Теория SQL — декларативный язык: ты описываешь, какие данные нужны, а СУБД решает, как их достать. Базовый pipeline: SELECT колонки FROM таблицы WHERE условие ORDER BY сортировка LIMI…"} \ No newline at end of file diff --git a/docs/weeks/18.json b/docs/weeks/18.json index badaf37..e113e29 100644 --- a/docs/weeks/18.json +++ b/docs/weeks/18.json @@ -1 +1 @@ -{"id": "week-18", "title": "FastAPI", "fullTitle": "Неделя 18: SQLAlchemy ORM + FastAPI", "html": "

                                                                                                                                                                                                                        Неделя 18: SQLAlchemy ORM + FastAPI

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: построить типобезопасный REST API на Python с ORM и автодокументацией.\nЛитература: SQLAlchemy 2.0 ORM, FastAPI Tutorial, Pydantic\nПроект недели: Library REST API — FastAPI + SQLAlchemy, full CRUD, pytest ≥ 8, Swagger.\nGit: папка learning-log/week-18/, feature-ветки по роутерам; тег week-18-done.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 120 (Пн): SQLAlchemy — модели и сессии

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        SQLAlchemy 2.0 — современный ORM для Python. DeclarativeBase, Mapped[type] и mapped_column() задают модели типобезопасно. Engine — подключение к PostgreSQL; SessionLocal — фабрика сессий. Сессия — unit of work: session.add(obj), commit(), refresh(obj) для актуализации из БД.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        relationship() с back_populates связывает Author и Book двусторонне без ручных JOIN в каждом запросе. ORM model (Author в models/) — внутреннее представление; Pydantic schema (AuthorRead) — контракт API. Не смешивай их: утечёт password_hash в JSON.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        get_db() generator с yield и finally: session.close() — паттерн для FastAPI. Alembic версионирует схему (обзор); на этой неделе достаточно create_all + seed. Забытый commit() — данные «исчезают» после перезапуска.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: ORM model ≠ API schema; сессия — граница транзакции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Проект library-api, venv, pip install sqlalchemy psycopg2-binary python-dotenv
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Модели Author, Book с one-to-many relationship
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. database.py: engine, SessionLocal, get_db() generator с yield
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. init_db.py — create tables, seed 3 authors, 10 books
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь таблицы в psql/DBeaver после init
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. models/__init__.py — чистая структура пакета
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] SQLAlchemy 2.0 style (Mapped, mapped_column)\n- [ ] relationship двусторонний с back_populates\n- [ ] Таблицы создаются в PostgreSQL

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Проект library-api, venv, pip install sqlalchemy psycopg2-binary python-dotenv
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Модели Author, Book с one-to-many relationship
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. database.py: engine, SessionLocal, get_db() generator с yield
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m \"week 18 day 120: SQLAlchemy models and init_db\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Забытый session.commit() — данные не сохраняются
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Lazy loading вне session — DetachedInstanceError
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 121 (Вт): CRUD через ORM и запросы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CRUD через ORM использует SQLAlchemy 2.0 style select(), не legacy session.query(). session.get(Model, id) — lookup по primary key с identity map cache. session.scalars(select(Book).where(...)).all() возвращает список ORM-объектов. Фильтры: .where(), .join(), .order_by(), .limit(), .offset() для пагинации.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        N+1 problem: цикл по авторам + author.books внутри генерирует запрос на каждую итерацию. Решение — eager loading: selectinload(Author.books) или joinedload. Замерь количество SQL-запросов до и после — наглядный урок.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        session.delete(obj) + commit() удаляет с учётом cascade rules. Пагинация page=1, size=20 — обязательна для API endpoints. Вынеси CRUD в crud/authors.py — routes остаются тонкими. title.ilike('%python%') — case-insensitive поиск в PostgreSQL.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: N+1 лечится eager loading; select() API — стандарт SQLAlchemy 2.0.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. CRUD: create_author, get_authors, update_book, delete_book
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Запрос: все книги автора с join через relationship или explicit join
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Пагинация: get_books(page=1, size=20)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Замер N+1: цикл authors без selectinload vs с selectinload — считай запросы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Фильтр: книги где title.ilike('%python%')
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Вынеси CRUD в crud/authors.py, crud/books.py
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] select() API, не legacy Query (1.x)\n- [ ] N+1 продемонстрирован и исправлен\n- [ ] Пагинация работает

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. CRUD: create_author, get_authors, update_book, delete_book
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Запрос: все книги автора с join через relationship или explicit join
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Пагинация: get_books(page=1, size=20)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m \"week 18 day 121: ORM CRUD and N+1 fix\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • N+1: цикл по authors + author.books внутри — сотни запросов
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • session.query() — legacy, используй select()
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 122 (Ср): FastAPI — первый API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        FastAPI — ASGI-фреймворк с автоматической валидацией из type hints. Path params (/notes/{id}), query params (?skip=0), request body (Pydantic model) — три входа данных. Pydantic проверяет типы в runtime и генерирует OpenAPI schema для Swagger.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        uvicorn main:app --reload — dev-сервер с hot reload. /docs (Swagger UI) и /redoc — бесплатная интерактивная документация. response_model=NoteRead отсекает внутренние поля ORM от публичного JSON. Невалидный body → 422 Unprocessable Entity с деталями ошибок.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Начни с in-memory CRUD для Note — отдели изучение FastAPI от SQLAlchemy. NoteCreate, NoteRead, NoteUpdate (optional fields) — три схемы для разных операций. Mutable default в Pydantic: Field(default_factory=list), не tags=[].

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: type hints + Pydantic = валидация и docs из коробки; response_model защищает API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. main.py: FastAPI app, GET /health{\"status\": \"ok\"}
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. In-memory CRUD для Note (id, title, body) — без БД пока
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Pydantic: NoteCreate, NoteRead, NoteUpdate (все поля optional)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь Swagger UI — все endpoints с примерами
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Отправь невалидный body — убедись в 422 Unprocessable Entity
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Настрой pyproject.toml или requirements.txt с версиями
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] 422 при невалидном body\n- [ ] Response model отделён от create model\n- [ ] uvicorn --reload работает

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. main.py: FastAPI app, GET /health{\"status\": \"ok\"}
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. In-memory CRUD для Note (id, title, body) — без БД пока
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Pydantic: NoteCreate, NoteRead, NoteUpdate (все поля optional)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m \"week 18 day 122: FastAPI in-memory notes API\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Mutable default list в Pydantic — Field(default_factory=list)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Возврат ORM object без response_model — утечка внутренних полей
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 123 (Чт): Dependency Injection и подключение БД

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Dependency Injection в FastAPI — через Depends. get_db() с yield создаёт сессию на один request и закрывает в finally — не используй глобальную session (race conditions). Depends(get_db) в параметрах endpoint автоматически резолвит зависимость.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        HTTPException(status_code=404, detail=\"Author not found\") — контролируемые ошибки вместо 500. Семантика статусов: 200 OK, 201 Created, 204 No Content, 404 Not Found, 409 Conflict, 422 Validation Error. Вложенные dependencies (get_current_user на нед. 20) строят цепочку проверок.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Pydantic schemas AuthorCreate / AuthorRead отделяют вход и выход. Nested resource GET /authors/{id}/books — RESTful вложенность. Lifespan events (startup/shutdown) — для инициализации пула и закрытия соединений (обзор).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: одна DB session на request через Depends; HTTPException — явные ошибки API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи SQLAlchemy к FastAPI через Depends(get_db)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. GET /authors, POST /authors, GET /authors/{id}
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. 404 если author не найден — HTTPException
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. GET /authors/{id}/books — nested resource
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Pydantic schemas: AuthorCreate, AuthorRead, BookRead
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Проверь в Swagger: create → get by id → list books
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] DB session закрывается после каждого request\n- [ ] HTTPException с detail message\n- [ ] Endpoints покрывают CRUD authors

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи SQLAlchemy к FastAPI через Depends(get_db)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. GET /authors, POST /authors, GET /authors/{id}
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. 404 если author не найден — HTTPException
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m \"week 18 day 123: FastAPI DI and authors endpoints\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Глобальная session — race conditions и утечки
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • 200 на DELETE несуществующего — должен быть 404
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 124 (Пт): Полный REST API «Библиотека»

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        REST — соглашения, не протокол. URL — существительные (/books), HTTP verbs — действия (GET читать, POST создать, PUT/PATCH обновить, DELETE удалить). GET, PUT, DELETE идемпотентны: повторный запрос даёт тот же эффект. POST — нет (каждый создаёт новый ресурс).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        APIRouter модульно группирует endpoints: routers/authors.py, prefix /api/v1, tags для Swagger. Пагинация в едином формате: { items, total, page, size }. Фильтрация через query: ?status=active&search=python. Версионирование /api/v1 защищает фронтенд от breaking changes.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Бизнес-правила в API: нельзя выдать уже выданную книгу → 409 Conflict, не 500. Глаголы в URL (/getAuthors) — антипаттерн. Отсутствие валидации FK — 500 вместо понятного 404.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: REST = ресурсы + HTTP semantics; 409 для нарушения бизнес-правил.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Роутеры: routers/authors.py, books.py, loans.py
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CRUD для books и loans с Pydantic validation
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. POST /loans — проверка: книга доступна? иначе 409
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. GET /books?author_id=1&search=python — фильтрация
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Подключи роутеры в main.py с prefix /api/v1
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Обнови Swagger — все endpoints сгруппированы по тегам
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] APIRouter + prefix /api/v1\n- [ ] Бизнес-правило: нельзя выдать уже выданную книгу → 409\n- [ ] Swagger актуален

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Роутеры: routers/authors.py, books.py, loans.py
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CRUD для books и loans с Pydantic validation
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. POST /loans — проверка: книга доступна? иначе 409
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m \"week 18 day 124: full library REST routers\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Глаголы в URL: /getAuthors — не REST
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Отсутствие валидации foreign key — 500 вместо 404
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 125 (Сб): Тестирование API и обработка ошибок

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тестирование API — страховка от регрессий. FastAPI TestClient (на базе httpx) шлёт запросы без реального сетевого сервера. pytest fixtures в conftest.py: client, db session, sample data. Test DB — отдельная schema или SQLite in-memory; никогда production.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Arrange-Act-Assert: подготовь данные, выполни запрос, проверь status и body. Тесты: create author 201, get missing 404, loan conflict 409. pytest -v --tb=short — читаемый вывод. Rollback после каждого теста — иначе flaky tests.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Global exception handlers: IntegrityError → 409, generic → 500 без stack trace в production. CORS middleware понадобится на нед. 21. Coverage pytest --cov=app показывает пробелы. ≥ 8 тестов — минимум для уверенности в CRUD и ошибках.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: изолированная test DB; тесты на auth, 404, 409 — не только happy path.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. pip install pytest httpx
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Тесты: create author, get 404, create loan conflict → 409
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. conftest.py — fixture test client + test db (rollback после теста)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Exception handler для SQLAlchemy IntegrityError
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Тест пагинации и фильтрации books
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь pytest в README и CI-заготовку
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] ≥ 8 pytest тестов, все проходят\n- [ ] Test DB изолирована от dev\n- [ ] pytest -v в README

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. pip install pytest httpx
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Тесты: create author, get 404, create loan conflict → 409
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. conftest.py — fixture test client + test db (rollback после теста)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m \"week 18 day 125: pytest suite and error handlers\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Тесты на production DB — никогда
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Забытый rollback после теста — flaky tests
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 126 (Вс): Ревью и документация API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        OpenAPI schema FastAPI генерирует из type hints и Pydantic — docs всегда синхронны с кодом, если ты дисциплинирован. README capstone-уровня: архитектура слоёв (routes → crud → models → db), env vars, curl-примеры, запуск postgres через docker. Postman collection — ручное тестирование для демо.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        12 Factor App: config через environment, не hardcode. .env.example без секретов. Mermaid-диаграмма слоёв в README помогает объяснить проект за 2 минуты. Логирование через logging module: INFO в production, DEBUG в dev.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Финальный прогон: pytest, uvicorn, ручная проверка Swagger. Library REST API — шаблон для Express на нед. 19 и DevHub на нед. 22. Тег week-18-done завершает первый production-like Python backend.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: документация API — часть deliverable; OpenAPI из кода, не из Word.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. README: архитектура, запуск, env vars, примеры curl
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. .env.example: DATABASE_URL, APP_ENV=development
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Export Postman collection JSON в docs/postman/
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Mermaid-диаграмма слоёв: routes → crud → models → db
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. curl-примеры для всех основных endpoints в README
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Финальный прогон: pytest, uvicorn, Swagger manual check
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] curl примеры для всех основных endpoints\n- [ ] Структура проекта понятна новому разработчику\n- [ ] docker run postgres документирован

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. README: архитектура, запуск, env vars, примеры curl
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. .env.example: DATABASE_URL, APP_ENV=development
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Export Postman collection JSON в docs/postman/
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m \"week 18 day 126: API docs and Postman collection\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поставь тег: git tag week-18-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        REST API «Библиотека» — production-ready Python backend. Спецификация: docs/projects.md — неделя 18.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Стек и структура

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        week-18/\n├── app/\n│   ├── main.py\n│   ├── database.py\n│   ├── models/\n│   ├── schemas/\n│   ├── crud/\n│   └── routers/\n├── tests/\n│   └── conftest.py\n├── requirements.txt\n├── .env.example\n└── README.md\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. FastAPI + SQLAlchemy 2.0 + PostgreSQL
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Authors, Books, Borrowers, Loans — full CRUD
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Dependency injection, Pydantic schemas, APIRouter
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Seed script, pytest (≥ 8 тестов)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Swagger /docs, Postman collection, README
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Данные в PostgreSQL, не in-memory
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Foreign keys и бизнес-правила займов (409 при конфликте)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • 404/409/422 обработаны корректно
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Все тесты зелёные: pytest -v
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • OpenAPI /docs актуален и совпадает с реализацией
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • README: clone → venv → migrate → seed → run → test
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Тег week-18-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Чем ORM отличается от raw SQL? Плюсы и минусы?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что такое N+1 и как исправить в SQLAlchemy?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Зачем Pydantic models отдельно от ORM models?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как работает Depends(get_db)?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что такое idempotent HTTP method? Примеры.
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Library REST API** в `learning-log/week-18/`, осмысленная Git-история, тег `week-18-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nFastAPI + SQLAlchemy REST API\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-18-day-120", "label": "День 120 (Пн): SQLAlchemy — модели и сессии"}, {"id": "week-18-day-121", "label": "День 121 (Вт): CRUD через ORM и запросы"}, {"id": "week-18-day-122", "label": "День 122 (Ср): FastAPI — первый API"}, {"id": "week-18-day-123", "label": "День 123 (Чт): Dependency Injection и подключение БД"}, {"id": "week-18-day-124", "label": "День 124 (Пт): Полный REST API «Библиотека»"}, {"id": "week-18-day-125", "label": "День 125 (Сб): Тестирование API и обработка ошибок"}, {"id": "week-18-day-126", "label": "День 126 (Вс): Ревью и документация API"}, {"id": "week-18-project", "label": "Проект недели"}, {"id": "week-18-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-18-review", "label": "Проверь себя"}], "text": "Неделя 18: SQLAlchemy ORM + FastAPI Цель недели: построить типобезопасный REST API на Python с ORM и автодокументацией. Литература: SQLAlchemy 2.0 ORM , FastAPI Tutorial , Pydantic Проект недели: Library REST API — FastAPI + SQLAlchemy, full CRUD, pytest ≥ 8, Swagger. Git: папка learning-log/week-18/ , feature-ветки по роутерам; тег week-18-done . День 120 (Пн): SQLAlchemy — модели и сессии Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Library REST API Теория SQLAlchemy 2.0 — современный ORM для Python. DeclarativeBase, Mapped[type] и mapped_column() задают модели типобезопасно. Engine — подключение к PostgreSQL; SessionLocal — фабрика сессий. Сессия — unit of work: session.add(obj) , c…"} \ No newline at end of file +{"id": "week-18", "title": "FastAPI", "fullTitle": "Неделя 18: SQLAlchemy ORM + FastAPI", "html": "

                                                                                                                                                                                                                        Неделя 18: SQLAlchemy ORM + FastAPI

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: построить типобезопасный REST API на Python с ORM и автодокументацией.\nЛитература: SQLAlchemy 2.0 ORM, FastAPI Tutorial, Pydantic\nПроект недели: Library REST API — FastAPI + SQLAlchemy, full CRUD, pytest ≥ 8, Swagger.\nGit: папка learning-log/week-18/, feature-ветки по роутерам; тег week-18-done.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 120 (Пн): SQLAlchemy — модели и сессии

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        SQLAlchemy 2.0 — современный ORM для Python. DeclarativeBase, Mapped[type] и mapped_column() задают модели типобезопасно. Engine — подключение к PostgreSQL; SessionLocal — фабрика сессий. Сессия — unit of work: session.add(obj), commit(), refresh(obj) для актуализации из БД.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        relationship() с back_populates связывает Author и Book двусторонне без ручных JOIN в каждом запросе. ORM model (Author в models/) — внутреннее представление; Pydantic schema (AuthorRead) — контракт API. Не смешивай их: утечёт password_hash в JSON.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        get_db() generator с yield и finally: session.close() — паттерн для FastAPI. Alembic версионирует схему (обзор); на этой неделе достаточно create_all + seed. Забытый commit() — данные «исчезают» после перезапуска.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: сессия SQLAlchemy — это «корзина покупок». Ты добавляешь и меняешь объекты (session.add(book), book.title = '...') — они лежат в корзине как черновик, видимый только тебе. Ничего не попадает на «склад» (в таблицы БД) до commit(); если передумал — rollback() выбрасывает всё содержимое корзины без следа. Это разделение «черновик в памяти» и «зафиксированное состояние в БД» — ключ к пониманию, почему объект может «казаться сохранённым» в текущем коде, но исчезнуть при следующем запуске программы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Синтаксис моделей, который ты пишешь сегодня, — это не просто ORM-специфика: class Author(Base): id: Mapped[int] = mapped_column(primary_key=True) — прямое продолжение классов и type hints с недели 16, применённое к описанию таблиц. А паттерн get_db() с yield и закрытием сессии в finally — это заготовка для Dependency Injection, которую ты формализуешь через Depends() уже послезавтра, и она же концептуально повторится в Node.js как «одно соединение из пула на один запрос» на неделе 19.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать ORM-модель (Author из models/) и Pydantic-схему (AuthorRead для API) одной и той же сущностью, которую можно возвращать из эндпоинта напрямую. Это разные слои с разными целями: ORM-модель отражает структуру таблицы и может содержать чувствительные или внутренние поля (password_hash, internal_notes), а API-схема — это явно объявленный публичный контракт. Смешение слоёв — прямой путь к утечке данных в JSON-ответе. Вторая типичная ошибка — забыть session.commit(), из-за чего изменения видны в рамках текущего процесса (SQLAlchemy их закэшировал), но исчезают после перезапуска сервера, потому что физически не записаны в PostgreSQL.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: ORM model ≠ API schema; сессия — граница транзакции.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Проект library-api, venv, pip install sqlalchemy psycopg2-binary python-dotenv
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Модели Author, Book с one-to-many relationship
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. database.py: engine, SessionLocal, get_db() generator с yield
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. init_db.py — create tables, seed 3 authors, 10 books
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь таблицы в psql/DBeaver после init
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. models/__init__.py — чистая структура пакета
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] SQLAlchemy 2.0 style (Mapped, mapped_column)\n- [ ] relationship двусторонний с back_populates\n- [ ] Таблицы создаются в PostgreSQL

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Проект library-api, venv, pip install sqlalchemy psycopg2-binary python-dotenv
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Модели Author, Book с one-to-many relationship
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. database.py: engine, SessionLocal, get_db() generator с yield
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m \"week 18 day 120: SQLAlchemy models and init_db\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Забытый session.commit() — данные не сохраняются
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Lazy loading вне session — DetachedInstanceError
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 121 (Вт): CRUD через ORM и запросы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CRUD через ORM использует SQLAlchemy 2.0 style select(), не legacy session.query(). session.get(Model, id) — lookup по primary key с identity map cache. session.scalars(select(Book).where(...)).all() возвращает список ORM-объектов. Фильтры: .where(), .join(), .order_by(), .limit(), .offset() для пагинации.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        N+1 problem: цикл по авторам + author.books внутри генерирует запрос на каждую итерацию. Решение — eager loading: selectinload(Author.books) или joinedload. Замерь количество SQL-запросов до и после — наглядный урок.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        session.delete(obj) + commit() удаляет с учётом cascade rules. Пагинация page=1, size=20 — обязательна для API endpoints. Вынеси CRUD в crud/authors.py — routes остаются тонкими. title.ilike('%python%') — case-insensitive поиск в PostgreSQL.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель N+1: представь, что нужно доставить книги 20 авторов, но вместо одной фуры, которая привозит всё за один рейс (selectinload — один дополнительный запрос со списком id), курьер каждый раз едет на склад за книгами одного конкретного автора — 20 отдельных поездок. Каждое обращение к author.books внутри цикла без eager loading — это отдельный SQL-запрос к базе, и для 100 авторов это будет 101 запрос вместо 2.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        N+1 — не теоретическая проблема из учебника: это самая частая жалоба на производительность в production API, построенных на ORM, и именно её ты научишься видеть и чинить сегодня. В любом реальном проекте на SQLAlchemy, который ты соберёшь после курса, первый вопрос при жалобе «эндпоинт тормозит» — это «сколько SQL-запросов он генерирует», и умение включить логирование запросов и посчитать их — прямой навык из сегодняшней практики.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что раз session.query() (SQLAlchemy 1.x) всё ещё работает и встречается в старых туториалах, значит это актуальный способ писать запросы. Однако 2.0-style select() — новый стандарт с лучшей типизацией и явным поведением, и весь код недели построен на нём. Вторая ошибка — включать eager loading (selectinload) на все связи по умолчанию «на всякий случай»: это не бесплатно, каждая дополнительная связь — дополнительный запрос или JOIN, поэтому выбор между selectinload и joinedload должен опираться на реальный паттерн использования, а не привычку. Практическая привычка на будущее: при любом подозрении на медленный endpoint включай логирование SQL (echo=True в engine) и считай запросы за один HTTP-вызов — это тот же диагностический рефлекс, что и EXPLAIN ANALYZE на прошлой неделе, только применённый к ORM-коду.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: N+1 лечится eager loading; select() API — стандарт SQLAlchemy 2.0.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. CRUD: create_author, get_authors, update_book, delete_book
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Запрос: все книги автора с join через relationship или explicit join
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Пагинация: get_books(page=1, size=20)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Замер N+1: цикл authors без selectinload vs с selectinload — считай запросы
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Фильтр: книги где title.ilike('%python%')
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Вынеси CRUD в crud/authors.py, crud/books.py
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] select() API, не legacy Query (1.x)\n- [ ] N+1 продемонстрирован и исправлен\n- [ ] Пагинация работает

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. CRUD: create_author, get_authors, update_book, delete_book
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Запрос: все книги автора с join через relationship или explicit join
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Пагинация: get_books(page=1, size=20)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m \"week 18 day 121: ORM CRUD and N+1 fix\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • N+1: цикл по authors + author.books внутри — сотни запросов
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • session.query() — legacy, используй select()
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 122 (Ср): FastAPI — первый API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        FastAPI — ASGI-фреймворк с автоматической валидацией из type hints. Path params (/notes/{id}), query params (?skip=0), request body (Pydantic model) — три входа данных. Pydantic проверяет типы в runtime и генерирует OpenAPI schema для Swagger.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        uvicorn main:app --reload — dev-сервер с hot reload. /docs (Swagger UI) и /redoc — бесплатная интерактивная документация. response_model=NoteRead отсекает внутренние поля ORM от публичного JSON. Невалидный body → 422 Unprocessable Entity с деталями ошибок.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Начни с in-memory CRUD для Note — отдели изучение FastAPI от SQLAlchemy. NoteCreate, NoteRead, NoteUpdate (optional fields) — три схемы для разных операций. Mutable default в Pydantic: Field(default_factory=list), не tags=[].

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель FastAPI — «contract-first без отдельного контракта»: обычно документацию API пишут отдельно от кода, и она рассинхронизируется через месяц. Здесь type hints и Pydantic-модель — это и есть контракт: FastAPI читает их один раз при старте и генерирует из них одновременно валидацию, сериализацию и Swagger-документацию. Написал title: str — и невалидный запрос без title автоматически получит 422 с понятным объяснением, без единой строчки ручной проверки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Почему это выходит за рамки одного дня: дисциплина response_model, которую ты закладываешь здесь на игрушечном Note, — это тот самый механизм, который через два дня не даст утечь внутренним полям ORM-модели (password_hash, internal_id) в публичный JSON API «Библиотеки». А привычка объявлять отдельные схемы для создания, чтения и обновления (NoteCreate без id, NoteRead с id, NoteUpdate с опциональными полями) — стандартный паттерн, который ты повторишь для Author, Book, Loan уже завтра.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что раз Pydantic валидирует типы, значит любые дефолтные значения безопасны, включая tags: list[str] = []. В чистом Python mutable default-аргумент функции действительно опасен — он создаётся один раз и разделяется между вызовами; Pydantic обрабатывает этот случай корректно сам, но Field(default_factory=list) — явный, самодокументируемый способ показать намерение и защититься от этой более общей проблемы Python, если она встретится вне Pydantic. Вторая ошибка новичков — возвращать ORM- или dict-объект напрямую без response_model, из-за чего в ответе оказываются лишние или чувствительные поля, которые никто не собирался показывать наружу. /docs и /redoc при этом не два независимых артефакта, а два разных представления одной и той же OpenAPI-схемы — Swagger удобен для ручного тестирования прямо из браузера, ReDoc — для чтения документации как справочника.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: type hints + Pydantic = валидация и docs из коробки; response_model защищает API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. main.py: FastAPI app, GET /health{\"status\": \"ok\"}
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. In-memory CRUD для Note (id, title, body) — без БД пока
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Pydantic: NoteCreate, NoteRead, NoteUpdate (все поля optional)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь Swagger UI — все endpoints с примерами
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Отправь невалидный body — убедись в 422 Unprocessable Entity
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Настрой pyproject.toml или requirements.txt с версиями
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] 422 при невалидном body\n- [ ] Response model отделён от create model\n- [ ] uvicorn --reload работает

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. main.py: FastAPI app, GET /health{\"status\": \"ok\"}
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. In-memory CRUD для Note (id, title, body) — без БД пока
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Pydantic: NoteCreate, NoteRead, NoteUpdate (все поля optional)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m \"week 18 day 122: FastAPI in-memory notes API\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Mutable default list в Pydantic — Field(default_factory=list)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Возврат ORM object без response_model — утечка внутренних полей
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 123 (Чт): Dependency Injection и подключение БД

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Dependency Injection в FastAPI — через Depends. get_db() с yield создаёт сессию на один request и закрывает в finally — не используй глобальную session (race conditions). Depends(get_db) в параметрах endpoint автоматически резолвит зависимость.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        HTTPException(status_code=404, detail=\"Author not found\") — контролируемые ошибки вместо 500. Семантика статусов: 200 OK, 201 Created, 204 No Content, 404 Not Found, 409 Conflict, 422 Validation Error. Вложенные dependencies (get_current_user на нед. 20) строят цепочку проверок.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Pydantic schemas AuthorCreate / AuthorRead отделяют вход и выход. Nested resource GET /authors/{id}/books — RESTful вложенность. Lifespan events (startup/shutdown) — для инициализации пула и закрытия соединений (обзор).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель Depends() — вендинговый автомат: ты не заботишься, как приготовлен кофе, ты просто объявляешь «мне нужна сессия БД» в параметрах функции-эндпоинта, а FastAPI сам вызывает get_db(), отдаёт тебе готовую сессию и гарантированно закрывает её после ответа — даже если внутри эндпоинта произошло исключение. Ты декларируешь зависимость, а не управляешь её жизненным циклом руками.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это не разовый трюк для сегодняшнего дня: ровно тот же механизм Depends станет способом получить текущего аутентифицированного пользователя (get_current_user) на неделе 20 — сегодняшний Depends(get_db) это буквально тренировочная версия завтрашней цепочки проверок доступа. Понимание, что зависимости можно комбинировать и они выполняются перед телом эндпоинта, снимает половину вопросов про то, «как вообще работает auth» позже.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать, что одна глобальная сессия на всё приложение (созданная один раз при старте) — безобидная оптимизация, которая экономит ресурсы. На самом деле под конкурентной нагрузкой это прямой путь к состоянию гонки: два одновременных запроса начнут писать в одну и ту же сессию, и данные одного пользователя могут утечь в ответ другому или вызвать неконсистентные commit. Вторая ошибка — возвращать 200 OK при удалении несуществующего ресурса вместо честного 404 через HTTPException: API должен явно сообщать о промахе, а не молча делать вид, что всё прошло успешно. Nested resource GET /authors/{id}/books заслуживает отдельного внимания: это не отдельная таблица, а тот же relationship, показанный под другим URL — RESTful вложенность выражает связь между ресурсами через структуру пути, а не через отдельный, никак не связанный endpoint.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: одна DB session на request через Depends; HTTPException — явные ошибки API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи SQLAlchemy к FastAPI через Depends(get_db)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. GET /authors, POST /authors, GET /authors/{id}
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. 404 если author не найден — HTTPException
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. GET /authors/{id}/books — nested resource
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Pydantic schemas: AuthorCreate, AuthorRead, BookRead
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Проверь в Swagger: create → get by id → list books
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] DB session закрывается после каждого request\n- [ ] HTTPException с detail message\n- [ ] Endpoints покрывают CRUD authors

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Подключи SQLAlchemy к FastAPI через Depends(get_db)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. GET /authors, POST /authors, GET /authors/{id}
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. 404 если author не найден — HTTPException
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m \"week 18 day 123: FastAPI DI and authors endpoints\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Глобальная session — race conditions и утечки
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • 200 на DELETE несуществующего — должен быть 404
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 124 (Пт): Полный REST API «Библиотека»

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        REST — соглашения, не протокол. URL — существительные (/books), HTTP verbs — действия (GET читать, POST создать, PUT/PATCH обновить, DELETE удалить). GET, PUT, DELETE идемпотентны: повторный запрос даёт тот же эффект. POST — нет (каждый создаёт новый ресурс).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        APIRouter модульно группирует endpoints: routers/authors.py, prefix /api/v1, tags для Swagger. Пагинация в едином формате: { items, total, page, size }. Фильтрация через query: ?status=active&search=python. Версионирование /api/v1 защищает фронтенд от breaking changes.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Бизнес-правила в API: нельзя выдать уже выданную книгу → 409 Conflict, не 500. Глаголы в URL (/getAuthors) — антипаттерн. Отсутствие валидации FK — 500 вместо понятного 404.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель REST: URL — это витрина магазина с существительными на ценниках (/books, /authors), а HTTP-глагол — это то, что ты делаешь с товаром на этой витрине (посмотреть — GET, положить в корзину — POST, поменять — PUT/PATCH, убрать — DELETE). Действие никогда не должно быть зашито в само название полки; если тянет написать /getBooks или /createAuthor, это сигнал, что мышление соскользнуло с ресурсов на процедуры.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура routers/authors.py, books.py, loans.py с общим префиксом /api/v1, которую ты собираешь сегодня, — прямой аналог того, что ты построишь в Express на неделе 19 через routes/, controllers/, services/: разные языки, одна и та же архитектурная идея модульного разделения по ресурсам. Сравнение этих двух реализаций в конце месяца станет наглядным доказательством, что архитектурное мышление важнее конкретного фреймворка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — трактовать любое нарушение бизнес-правила (книга уже выдана, лимит займов исчерпан) как ошибку сервера и возвращать 500. На деле это ожидаемая, предсказуемая ситуация в доменной логике, и правильный ответ — 409 Conflict с понятным сообщением, которое фронтенд может показать пользователю осмысленно. Вторая распространённая ошибка — не проверять существование внешнего ключа перед вставкой (например, author_id, которого нет), из-за чего клиент получает малопонятную 500-ю ошибку от БД вместо контролируемого 404 или 400 от приложения. Версионирование через префикс /api/v1 — ещё одна деталь, которую легко недооценить: она защищает уже подключившийся фронтенд от breaking changes, когда через несколько месяцев понадобится изменить форму ответа — старые клиенты продолжат работать с /api/v1, пока новые постепенно переходят на /api/v2.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: REST = ресурсы + HTTP semantics; 409 для нарушения бизнес-правил.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Роутеры: routers/authors.py, books.py, loans.py
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CRUD для books и loans с Pydantic validation
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. POST /loans — проверка: книга доступна? иначе 409
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. GET /books?author_id=1&search=python — фильтрация
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Подключи роутеры в main.py с prefix /api/v1
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Обнови Swagger — все endpoints сгруппированы по тегам
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] APIRouter + prefix /api/v1\n- [ ] Бизнес-правило: нельзя выдать уже выданную книгу → 409\n- [ ] Swagger актуален

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Роутеры: routers/authors.py, books.py, loans.py
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CRUD для books и loans с Pydantic validation
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. POST /loans — проверка: книга доступна? иначе 409
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m \"week 18 day 124: full library REST routers\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Глаголы в URL: /getAuthors — не REST
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Отсутствие валидации foreign key — 500 вместо 404
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 125 (Сб): Тестирование API и обработка ошибок

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тестирование API — страховка от регрессий. FastAPI TestClient (на базе httpx) шлёт запросы без реального сетевого сервера. pytest fixtures в conftest.py: client, db session, sample data. Test DB — отдельная schema или SQLite in-memory; никогда production.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Arrange-Act-Assert: подготовь данные, выполни запрос, проверь status и body. Тесты: create author 201, get missing 404, loan conflict 409. pytest -v --tb=short — читаемый вывод. Rollback после каждого теста — иначе flaky tests.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Global exception handlers: IntegrityError → 409, generic → 500 без stack trace в production. CORS middleware понадобится на нед. 21. Coverage pytest --cov=app показывает пробелы. ≥ 8 тестов — минимум для уверенности в CRUD и ошибках.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель TestClient — «робот-клиент», который стучится в твоё FastAPI-приложение напрямую в памяти, без реального TCP-сокета и сетевого стека. Отсюда и скорость (сотни тестов выполняются за секунды), и детерминированность (нет случайных сетевых задержек или занятых портов) — тесты можно гонять на каждый коммит без страха, что они станут узким местом разработки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Автотесты — это не формальность для галочки в критериях: именно они дают возможность бесстрашно рефакторить код проекта недели, зная, что любая регрессия будет поймана до того, как попадёт в продакшен. Это тот же навык и тот же паттерн Arrange-Act-Assert, который ты используешь на любой позиции разработчика, независимо от языка — pytest здесь, Jest/Vitest в Node-мире.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — писать тесты только на happy path («создание автора работает») и считать это достаточным покрытием. В реальности большинство продакшен-багов живёт именно в граничных случаях: что возвращается при 404, что происходит при попытке создать конфликтующий заём (409), что при невалидном body (422) — и сегодняшняя практика целенаправленно требует именно такие тесты. Вторая ошибка — забыть откат (rollback) состояния БД после каждого теста: без него тесты начинают зависеть от порядка выполнения и от результатов друг друга, превращаясь в нестабильные (flaky) — тест то падает, то проходит без изменений в коде. Global exception handler для IntegrityError (например, попытка создать книгу с несуществующим author_id) — та же идея централизованной обработки ошибок, которую ты применишь в Express на следующей неделе через error-middleware: одно место в коде решает, как любая непойманная ошибка конкретного типа превращается в понятный HTTP-ответ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: изолированная test DB; тесты на auth, 404, 409 — не только happy path.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. pip install pytest httpx
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Тесты: create author, get 404, create loan conflict → 409
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. conftest.py — fixture test client + test db (rollback после теста)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Exception handler для SQLAlchemy IntegrityError
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Тест пагинации и фильтрации books
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Добавь pytest в README и CI-заготовку
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] ≥ 8 pytest тестов, все проходят\n- [ ] Test DB изолирована от dev\n- [ ] pytest -v в README

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. pip install pytest httpx
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Тесты: create author, get 404, create loan conflict → 409
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. conftest.py — fixture test client + test db (rollback после теста)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m \"week 18 day 125: pytest suite and error handlers\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Тесты на production DB — никогда
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Забытый rollback после теста — flaky tests
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 126 (Вс): Ревью и документация API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Library REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        OpenAPI schema FastAPI генерирует из type hints и Pydantic — docs всегда синхронны с кодом, если ты дисциплинирован. README capstone-уровня: архитектура слоёв (routes → crud → models → db), env vars, curl-примеры, запуск postgres через docker. Postman collection — ручное тестирование для демо.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        12 Factor App: config через environment, не hardcode. .env.example без секретов. Mermaid-диаграмма слоёв в README помогает объяснить проект за 2 минуты. Логирование через logging module: INFO в production, DEBUG в dev.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Финальный прогон: pytest, uvicorn, ручная проверка Swagger. Library REST API — шаблон для Express на нед. 19 и DevHub на нед. 22. Тег week-18-done завершает первый production-like Python backend.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель для ревью-дня: README и OpenAPI-документация — это витрина твоего проекта. Первые две минуты, которые незнакомый разработчик (или нанимающий менеджер) проводит с репозиторием, определяют, доверяет ли он остальному коду. Хорошо структурированный README с архитектурной диаграммой и curl-примерами говорит «этот человек умеет думать о других разработчиках», даже если он ни разу не прочитает исходники.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Дисциплина документирования, которую ты закрепляешь сегодня — env vars, архитектура слоёв, инструкции запуска, — это не разовая задача для этого проекта: ты буквально повторишь тот же набор артефактов для Express-проекта на неделе 19 и для capstone DevHub на неделе 22, так что сегодняшний README становится шаблоном, который экономит время трижды.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать, что автоматически сгенерированный Swagger (/docs) полностью заменяет README. Swagger прекрасно показывает что доступно (endpoints, схемы, параметры), но не объясняет как поднять проект с нуля — какие переменные окружения нужны, как накатить миграции, откуда взять seed-данные и в каком порядке запускать команды. Именно поэтому оба артефакта нужны вместе, и критерий «структура проекта понятна новому разработчику» проверяется человеком, а не автогенерацией. Логирование через стандартный модуль logging (а не print) — ещё одна деталь взросления проекта: INFO в продакшене и DEBUG в разработке позволяют управлять шумом логов без правки кода, просто переменной окружения. Принцип 12 Factor App («конфигурация через переменные окружения, а не хардкод») — ещё одна деталь, которая перестаёт быть абстрактной рекомендацией и становится практическим требованием, как только проект нужно развернуть в контейнере: .env.example документирует, какие переменные обязательны, не раскрывая ни одного реального секрета.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: документация API — часть deliverable; OpenAPI из кода, не из Word.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. README: архитектура, запуск, env vars, примеры curl
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. .env.example: DATABASE_URL, APP_ENV=development
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Export Postman collection JSON в docs/postman/
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Mermaid-диаграмма слоёв: routes → crud → models → db
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. curl-примеры для всех основных endpoints в README
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Финальный прогон: pytest, uvicorn, Swagger manual check
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] curl примеры для всех основных endpoints\n- [ ] Структура проекта понятна новому разработчику\n- [ ] docker run postgres документирован

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. README: архитектура, запуск, env vars, примеры curl
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. .env.example: DATABASE_URL, APP_ENV=development
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Export Postman collection JSON в docs/postman/
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-18/git commit -m \"week 18 day 126: API docs and Postman collection\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поставь тег: git tag week-18-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        REST API «Библиотека» — production-ready Python backend. Спецификация: docs/projects.md — неделя 18.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Стек и структура

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        week-18/\n├── app/\n│   ├── main.py\n│   ├── database.py\n│   ├── models/\n│   ├── schemas/\n│   ├── crud/\n│   └── routers/\n├── tests/\n│   └── conftest.py\n├── requirements.txt\n├── .env.example\n└── README.md\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. FastAPI + SQLAlchemy 2.0 + PostgreSQL
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Authors, Books, Borrowers, Loans — full CRUD
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Dependency injection, Pydantic schemas, APIRouter
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Seed script, pytest (≥ 8 тестов)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Swagger /docs, Postman collection, README
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Данные в PostgreSQL, не in-memory
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Foreign keys и бизнес-правила займов (409 при конфликте)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • 404/409/422 обработаны корректно
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Все тесты зелёные: pytest -v
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • OpenAPI /docs актуален и совпадает с реализацией
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • README: clone → venv → migrate → seed → run → test
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Тег week-18-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Чем ORM отличается от raw SQL? Плюсы и минусы?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что такое N+1 и как исправить в SQLAlchemy?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Зачем Pydantic models отдельно от ORM models?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как работает Depends(get_db)?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что такое idempotent HTTP method? Примеры.
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Library REST API** в `learning-log/week-18/`, осмысленная Git-история, тег `week-18-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nFastAPI + SQLAlchemy REST API\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-18-day-120", "label": "День 120 (Пн): SQLAlchemy — модели и сессии"}, {"id": "week-18-day-121", "label": "День 121 (Вт): CRUD через ORM и запросы"}, {"id": "week-18-day-122", "label": "День 122 (Ср): FastAPI — первый API"}, {"id": "week-18-day-123", "label": "День 123 (Чт): Dependency Injection и подключение БД"}, {"id": "week-18-day-124", "label": "День 124 (Пт): Полный REST API «Библиотека»"}, {"id": "week-18-day-125", "label": "День 125 (Сб): Тестирование API и обработка ошибок"}, {"id": "week-18-day-126", "label": "День 126 (Вс): Ревью и документация API"}, {"id": "week-18-project", "label": "Проект недели"}, {"id": "week-18-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-18-review", "label": "Проверь себя"}], "text": "Неделя 18: SQLAlchemy ORM + FastAPI Цель недели: построить типобезопасный REST API на Python с ORM и автодокументацией. Литература: SQLAlchemy 2.0 ORM , FastAPI Tutorial , Pydantic Проект недели: Library REST API — FastAPI + SQLAlchemy, full CRUD, pytest ≥ 8, Swagger. Git: папка learning-log/week-18/ , feature-ветки по роутерам; тег week-18-done . День 120 (Пн): SQLAlchemy — модели и сессии Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Library REST API Теория SQLAlchemy 2.0 — современный ORM для Python. DeclarativeBase, Mapped[type] и mapped_column() задают модели типобезопасно. Engine — подключение к PostgreSQL; SessionLocal — фабрика сессий. Сессия — unit of work: session.add(obj) , co…"} \ No newline at end of file diff --git a/docs/weeks/19.json b/docs/weeks/19.json index 9dbfed8..eac6783 100644 --- a/docs/weeks/19.json +++ b/docs/weeks/19.json @@ -1 +1 @@ -{"id": "week-19", "title": "Node.js", "fullTitle": "Неделя 19: Node.js + Express REST API", "html": "

                                                                                                                                                                                                                        Неделя 19: Node.js + Express REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: построить REST API на JavaScript в среде Node.js с Express и PostgreSQL.\nЛитература: Node.js Docs, Express Guide, node-postgres\nПроект недели: Express Notes API — layered Express API, Zod, PostgreSQL, Postman collection.\nGit: папка learning-log/week-19/, ветки feature/routes, feature/pg; тег week-19-done.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 127 (Пн): Node.js — среда и модули

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Express Notes API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Node.js — среда выполнения JavaScript вне браузера. Нет DOM и window, зато есть process, встроенные модули и npm-экосистема. Backend на Node разделяет язык с фронтендом — один TypeScript/JavaScript на обе стороны, но runtime другой: event loop libuv, не браузерный.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CommonJS (require) vs ES Modules (import) — выбери \"type\": \"module\" в package.json для современного стиля. import.meta.url + fileURLToPath заменяют __dirname в ESM. Встроенные модули: fs, path, http. process.argv — аргументы CLI, process.env — переменные окружения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        npm управляет зависимостями: package.json, semver, node_modules. npm scripts (\"greet\": \"node scripts/greet.js\") — стандартный способ запуска задач. .gitignore: node_modules, .env. fs.promises вместо callback — async/await без callback hell.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: Node — JS без браузера; ESM + fs.promises — современный baseline.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. mkdir notes-api && npm init -y, добавь \"type\": \"module\"
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CLI: node scripts/greet.js --name=Alex (parse process.argv)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Чтение/запись notes.json через fs.promises
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. path.join, import.meta.url для путей к файлам данных
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. npm script \"greet\": \"node scripts/greet.js\"
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. .gitignore: node_modules, .env, dist
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] ES modules (import/export)\n- [ ] fs.promises, не callback fs.readFile\n- [ ] npm script \"greet\" работает

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. mkdir notes-api && npm init -y, добавь \"type\": \"module\"
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CLI: node scripts/greet.js --name=Alex (parse process.argv)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Чтение/запись notes.json через fs.promises
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-19/git commit -m \"week 19 day 127: Node ESM setup and file CLI\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • require() в ESM project — SyntaxError
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Относительные пути без path.join — ломается на Windows
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 128 (Вт): Асинхронность в Node

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Express Notes API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Асинхронность — сердце Node. Эволюция: callback → Promise → async/await. Event loop libuv обрабатывает I/O неблокирующе, но синхронный fs.readFileSync в сервере заморозит все запросы — используй async API. await без try/catch — необработанный rejection.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        EventEmitter (on, emit, once) — основа многих Node API и паттерн pub/sub. process.on('unhandledRejection') ловит забытые rejections — настрой в entry point. util.promisify оборачивает legacy callback API в Promise — для понимания, не для нового кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        File watcher на notes.json учит реагировать на изменения; SIGINT корректно останавливает watcher. Promise.all читает три файла параллельно. Замер sync vs async на 10 файлах — наглядная демонстрация блокировки main thread.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: не блокируй event loop; await + try/catch на каждом I/O.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши file I/O на async/await с try/catch
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. File watcher: логирует изменения notes.json, останавливается на SIGINT
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Промисификация: const readFile = promisify(fs.readFile) — для понимания legacy
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Обработка unhandledRejection и uncaughtException в entry point
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Параллельное чтение 3 файлов через Promise.all
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Замер: sync readFileSync vs async на 10 файлах — почувствуй блокировку
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Нет callback hell — только async/await\n- [ ] Watcher корректно останавливается (SIGINT)\n- [ ] try/catch вокруг await

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши file I/O на async/await с try/catch
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. File watcher: логирует изменения notes.json, останавливается на SIGINT
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Промисификация: const readFile = promisify(fs.readFile) — для понимания legacy
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-19/git commit -m \"week 19 day 128: async file watcher and error handling\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Забытый await — Promise вместо данных
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Синхронный fs.readFileSync в сервере — блокирует event loop
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 129 (Ср): Express — REST API основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Express Notes API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Express — минималистичный HTTP-фреймворк поверх Node http. app.get/post/put/delete маппят метод + путь на handler. req.params — path params, req.query — query string, req.body — JSON после express.json() middleware. Без body parser req.body будет undefined — классическая ловушка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        HTTP semantics: 200 OK, 201 Created, 204 No Content (DELETE без body), 400 Bad Request, 404 Not Found. Раздели app.js (конфигурация, middleware, routes) и server.js (listen) — app экспортируется для тестов. nodemon автоперезапускает в dev.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CRUD /api/notes с хранением в JSON-файле — мост к PostgreSQL завтра. Единый формат ответа { data } или { error: { message } } упрощает фронтенд. RESTful URLs: существительные, не глаголы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: express.json() обязателен; app отдельно от server — тестируемость.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install express, src/app.js, src/server.js
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CRUD /api/notes — хранение в JSON-файле через fs
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. GET /api/notes/:id — 404 если нет (res.status(404).json(...))
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. npm install -D nodemon, script \"dev\": \"nodemon src/server.js\"
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь все методы через curl или Thunder Client
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Единый формат ответа: { data } или { error: { message } }
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] express.json() подключён\n- [ ] RESTful URLs и методы\n- [ ] 201 на POST, 204 на DELETE

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install express, src/app.js, src/server.js
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CRUD /api/notes — хранение в JSON-файле через fs
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. GET /api/notes/:id — 404 если нет (res.status(404).json(...))
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-19/git commit -m \"week 19 day 129: Express CRUD notes in-memory JSON\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • POST без body parser — req.body undefined
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Один огромный app.js — разбей на routes
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 130 (Чт): Middleware, валидация, ошибки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Express Notes API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Middleware в Express — функции (req, res, next) в цепочке. Порядок критичен: logger → express.json() → routes → 404 handler → error middleware (4 аргумента: err, req, res, next). next() передаёт управление дальше; next(err) — в error handler.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Zod валидирует body с TypeScript inference: title min 1 символ, body optional. При ошибке — 400 с zodError.flatten(). Centralized error handler возвращает JSON { error: { code, message } } — единый контракт для клиента. morgan логирует HTTP-запросы в dev.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        404 handler для неизвестных routes — последний middleware перед error handler. Custom logger с duration (Date.now до/после) дополняет morgan. Error middleware без 4 параметров Express не распознает — не вызовется.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: порядок middleware; Zod на входе, error handler на выходе цепочки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Logger middleware: method, url, duration (Date.now до/после)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Zod schema для Note: title min 1, body optional string
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Centralized error handler — JSON { error: { code, message } }
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. 400 при validation error с деталями Zod (zodError.flatten())
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. 404 handler для неизвестных routes (app.use((req,res) => ...))
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. morgan 'dev' format в development
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Все ошибки проходят через error middleware\n- [ ] Zod на POST и PUT\n- [ ] morgan или custom logger

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Logger middleware: method, url, duration (Date.now до/после)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Zod schema для Note: title min 1, body optional string
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Centralized error handler — JSON { error: { code, message } }
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-19/git commit -m \"week 19 day 130: Zod validation and error middleware\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Забытый next(err) — зависший request
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Error middleware без 4 параметров — не вызывается
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 131 (Пт): Express + PostgreSQL

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~50м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~20м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Express Notes API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        node-postgres (pg) — драйвер PostgreSQL для Node. Pool переиспользует соединения под нагрузкой; new Client() на каждый запрос — антипаттерн. pool.query('SELECT * FROM notes WHERE id = $1', [id]) — placeholders $1, $2 защищают от SQL injection.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DATABASE_URL=postgresql://user:pass@host:5432/db из .env через dotenv. Prisma — ORM-альтернатива (обзор); на этой неделе raw pg учит SQL и placeholders. Graceful shutdown: pool.end() на SIGTERM.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Перепиши notes API с JSON-файла на таблицу notes(id, title, body, created_at). schema.sql + migrate script. Все запросы только через pool.query с массивом параметров — template strings в SQL запрещены.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: Pool, не Client; $1 placeholders — единственный безопасный способ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install pg dotenv
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. src/db/pool.js — Pool из DATABASE_URL, тест SELECT NOW()
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Перепиши notes API на таблицу notes(id, title, body, created_at)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. schema.sql + scripts/migrate.js или npm run db:migrate
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. seed.sql с 5 тестовыми заметками
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Все запросы через pool.query('... WHERE id = $1', [id])
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Pool, не Client на каждый запрос\n- [ ] Параметризованные запросы ($1, $2)\n- [ ] dotenv, .env.example

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install pg dotenv
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. src/db/pool.js — Pool из DATABASE_URL, тест SELECT NOW()
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Перепиши notes API на таблицу notes(id, title, body, created_at)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-19/git commit -m \"week 19 day 131: Express notes with PostgreSQL pool\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • SQL injection через template strings — только placeholders
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Pool не закрывается при shutdown — graceful exit
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 132 (Сб): Структура проекта и роутеры

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~50м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Express Notes API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Express Router модульно группирует маршруты: notes.routes.js монтируется с prefix /api/notes. Layered architecture: routes (тонкие) → controllers (HTTP) → services (бизнес-логика) → db (SQL). Бизнес-логика в route handler не тестируется — вынеси в service.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        dotenv загружает secrets из .env; NODE_ENV=development|production меняет поведение (morgan 'dev' vs 'combined'). Health check GET /api/health возвращает { status, db: 'ok'|'down', uptime } — нужен для Docker и мониторинга. 503 если БД недоступна.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Graceful shutdown: SIGTERM → server.close()pool.end(). package-lock.json в git — воспроизводимые сборки. README описывает слои папок — onboarding нового разработчика.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: routes тонкие, logic в services; health check — контракт с инфраструктурой.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Структура: src/routes/, controllers/, services/, db/pool.js
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Вынеси логику из routes в controller/service
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. GET /api/health{ status, db: 'ok'|'down', uptime }
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Router notes.routes.js → controller notes.controller.js → service notes.service.js
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Graceful shutdown: SIGTERM → close server → pool.end()
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. README: структура папок с описанием слоёв
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Routes тонкие — только маршрутизация\n- [ ] Service переиспользуется из controller\n- [ ] health check возвращает 503 если DB down

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Структура: src/routes/, controllers/, services/, db/pool.js
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Вынеси логику из routes в controller/service
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. GET /api/health{ status, db: 'ok'|'down', uptime }
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-19/git commit -m \"week 19 day 132: layered architecture and health check\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Бизнес-логика в route handler — не тестируется
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Циклические импорты между modules
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 133 (Вс): Ревью Node.js и сравнение с FastAPI

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Express Notes API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью недели — сравнение двух backend-стеков, которые ты теперь знаешь. FastAPI: автодоки, Pydantic, async, Python ecosystem. Express: минимализм, npm, один язык с React. Для I/O-bound оба отличны; CPU-bound тяжёлая работа чаще уходит в Python или отдельный worker.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        npm scripts best practices: start (production), dev (nodemon), test, db:migrate. Postman collection — демо и ручное QA. Skeleton auth.routes.js — мост к неделе 20. npm audit показывает уязвимости в зависимостях.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Сравнительная таблица FastAPI vs Express по 10 критериям учит аргументировать выбор стека. Express Notes API — parity с Library REST API недели 18: те же статусы, формат ошибок, layered structure. Тег week-19-done.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: Express и FastAPI решают одну задачу разными инструментами — выбор по команде и экосистеме.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сравнительная таблица: FastAPI (нед.18) vs Express — 10 критериев в docs/compare.md
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Postman collection для Express API — export JSON
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. README с curl примерами для всех endpoints
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Skeleton: src/routes/auth.routes.js с заглушками register/login
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. npm audit — отчёт об уязвимостях
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Финальный smoke test: CRUD notes через API
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] README полный (install, env, run, test)\n- [ ] Сравнительная таблица в docs\n- [ ] npm start и npm run dev работают

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сравнительная таблица: FastAPI (нед.18) vs Express — 10 критериев в docs/compare.md
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Postman collection для Express API — export JSON
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. README с curl примерами для всех endpoints
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-19/git commit -m \"week 19 day 133: docs, Postman, auth skeleton\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поставь тег: git tag week-19-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Express Notes API с PostgreSQL. Спецификация: docs/projects.md — неделя 19.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        week-19/\n├── src/\n│   ├── app.js\n│   ├── server.js\n│   ├── routes/\n│   ├── controllers/\n│   ├── services/\n│   ├── db/\n│   └── middleware/\n├── schema.sql\n├── docs/\n│   ├── postman-collection.json\n│   └── compare.md\n├── package.json\n├── .env.example\n└── README.md\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Full CRUD /api/notes
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Zod validation, error middleware, request logging (morgan)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Layered architecture: routes → controllers → services → db
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. PostgreSQL + migrations + seed
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Health check, graceful shutdown, Postman collection
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Production-like структура папок
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Все SQL через pool.query с placeholders
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Graceful shutdown (SIGTERM) закрывает pool
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Health endpoint возвращает статус БД
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Postman collection покрывает все endpoints
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Стиль API согласован с FastAPI проектом недели 18 (статусы, формат ошибок)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Тег week-19-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Node vs Browser JS — 3 главных отличия?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что делает middleware next()?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Зачем connection pool вместо одного client?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как валидировать body в Express?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • ESM vs CommonJS — что выбрал и почему?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Express Notes API** в `learning-log/week-19/`, осмысленная Git-история, тег `week-19-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nNode.js + Express layered API\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-19-day-127", "label": "День 127 (Пн): Node.js — среда и модули"}, {"id": "week-19-day-128", "label": "День 128 (Вт): Асинхронность в Node"}, {"id": "week-19-day-129", "label": "День 129 (Ср): Express — REST API основы"}, {"id": "week-19-day-130", "label": "День 130 (Чт): Middleware, валидация, ошибки"}, {"id": "week-19-day-131", "label": "День 131 (Пт): Express + PostgreSQL"}, {"id": "week-19-day-132", "label": "День 132 (Сб): Структура проекта и роутеры"}, {"id": "week-19-day-133", "label": "День 133 (Вс): Ревью Node.js и сравнение с FastAPI"}, {"id": "week-19-project", "label": "Проект недели"}, {"id": "week-19-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-19-review", "label": "Проверь себя"}], "text": "Неделя 19: Node.js + Express REST API Цель недели: построить REST API на JavaScript в среде Node.js с Express и PostgreSQL. Литература: Node.js Docs , Express Guide , node-postgres Проект недели: Express Notes API — layered Express API, Zod, PostgreSQL, Postman collection. Git: папка learning-log/week-19/ , ветки feature/routes , feature/pg ; тег week-19-done . День 127 (Пн): Node.js — среда и модули Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Express Notes API Теория Node.js — среда выполнения JavaScript вне браузера. Нет DOM и window , зато есть process , встроенные модули и npm-экосистема. Backend на Node разделяет язык с фронтендом — один TypeScript/JavaScript на обе стороны, но r…"} \ No newline at end of file +{"id": "week-19", "title": "Node.js", "fullTitle": "Неделя 19: Node.js + Express REST API", "html": "

                                                                                                                                                                                                                        Неделя 19: Node.js + Express REST API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: построить REST API на JavaScript в среде Node.js с Express и PostgreSQL.\nЛитература: Node.js Docs, Express Guide, node-postgres\nПроект недели: Express Notes API — layered Express API, Zod, PostgreSQL, Postman collection.\nGit: папка learning-log/week-19/, ветки feature/routes, feature/pg; тег week-19-done.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 127 (Пн): Node.js — среда и модули

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Express Notes API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Node.js — среда выполнения JavaScript вне браузера. Нет DOM и window, зато есть process, встроенные модули и npm-экосистема. Backend на Node разделяет язык с фронтендом — один TypeScript/JavaScript на обе стороны, но runtime другой: event loop libuv, не браузерный.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CommonJS (require) vs ES Modules (import) — выбери \"type\": \"module\" в package.json для современного стиля. import.meta.url + fileURLToPath заменяют __dirname в ESM. Встроенные модули: fs, path, http. process.argv — аргументы CLI, process.env — переменные окружения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        npm управляет зависимостями: package.json, semver, node_modules. npm scripts (\"greet\": \"node scripts/greet.js\") — стандартный способ запуска задач. .gitignore: node_modules, .env. fs.promises вместо callback — async/await без callback hell.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: Node.js — это тот же JavaScript, что и в браузере, но перенесённый в другую «комнату». Нет window, document, DOM — вместо них файловая система, сеть, процессы операционной системы. Синтаксис языка (переменные, функции, промисы) идентичен тому, что ты писал во фронтенд-частях курса, а вот доступное окружение и стандартная библиотека — совершенно другие, ориентированные на серверные задачи.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это разделение окружения — не просто теория для сегодняшнего дня: весь Express-сервер, который ты соберёшь на этой неделе, работает по тем же базовым принципам Node — process.env для конфигурации, fs.promises для чтения файлов, событийная модель без блокировки. А общий язык с фронтендом — одно из главных практических преимуществ Node-стека в реальных командах: один разработчик может писать и клиент, и сервер.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — свободно мешать require() (CommonJS) и import (ES Modules) в одном проекте, ожидая, что Node сам разберётся. На практике \"type\": \"module\" в package.json — это переключатель на весь пакет: если он выставлен, require() в .js-файлах перестаёт работать и нужно использовать import/export, а __dirname из CommonJS придётся заменить на fileURLToPath(import.meta.url). Смешение стилей — частый источник непонятных SyntaxError у новичков, и именно поэтому практика дня явно требует единый ESM-стиль во всём проекте. Ещё одна важная привычка — fs.promises вместо колбэков: старый стиль fs.readFile(path, (err, data) => {...}) легко превращается в «пирамиду проклятия» (callback hell) при вложенных операциях, тогда как await fs.promises.readFile(path) читается линейно, сверху вниз, как синхронный код, оставаясь при этом неблокирующим.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: Node — JS без браузера; ESM + fs.promises — современный baseline.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. mkdir notes-api && npm init -y, добавь \"type\": \"module\"
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CLI: node scripts/greet.js --name=Alex (parse process.argv)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Чтение/запись notes.json через fs.promises
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. path.join, import.meta.url для путей к файлам данных
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. npm script \"greet\": \"node scripts/greet.js\"
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. .gitignore: node_modules, .env, dist
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] ES modules (import/export)\n- [ ] fs.promises, не callback fs.readFile\n- [ ] npm script \"greet\" работает

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. mkdir notes-api && npm init -y, добавь \"type\": \"module\"
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CLI: node scripts/greet.js --name=Alex (parse process.argv)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Чтение/запись notes.json через fs.promises
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-19/git commit -m \"week 19 day 127: Node ESM setup and file CLI\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • require() в ESM project — SyntaxError
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Относительные пути без path.join — ломается на Windows
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 128 (Вт): Асинхронность в Node

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Express Notes API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Асинхронность — сердце Node. Эволюция: callback → Promise → async/await. Event loop libuv обрабатывает I/O неблокирующе, но синхронный fs.readFileSync в сервере заморозит все запросы — используй async API. await без try/catch — необработанный rejection.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        EventEmitter (on, emit, once) — основа многих Node API и паттерн pub/sub. process.on('unhandledRejection') ловит забытые rejections — настрой в entry point. util.promisify оборачивает legacy callback API в Promise — для понимания, не для нового кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        File watcher на notes.json учит реагировать на изменения; SIGINT корректно останавливает watcher. Promise.all читает три файла параллельно. Замер sync vs async на 10 файлах — наглядная демонстрация блокировки main thread.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель event loop — один официант на много столиков. Официант (главный поток Node) не готовит блюдо сам: он передаёт заказ на кухню (файловую систему, сеть, таймер через libuv) и тут же идёт принимать заказ у следующего столика, а не стоит и ждёт готовности. Когда блюдо готово, официант возвращается и подаёт его — это и есть callback/promise resolution. Именно эта модель позволяет Node одним потоком обслуживать тысячи одновременных соединений.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это критично для всего, что будет построено дальше: каждый route-обработчик в Express на этой неделе — асинхронная функция, и если внутри неё случайно окажется синхронный блокирующий вызов (fs.readFileSync на большом файле, тяжёлые вычисления в цикле), это заморозит обработку всех остальных пользователей сервера одновременно, а не только текущий запрос — потому что официант всего один. EventEmitter с методами on, emit, once — ещё один слой этой же модели: множество встроенных Node API (потоки, HTTP-сервер) построены на событиях, и понимание паттерна pub/sub здесь напрямую объясняет, как работают, например, обработчики req.on('data', ...) при чтении тела запроса вручную.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — думать, что async/await сам по себе даёт параллелизм. await внутри функции лишь приостанавливает выполнение этой функции до готовности промиса, но следующая строка кода не начнёт выполняться, пока не завершится текущая — если нужно выполнить три независимые операции одновременно, необходим явный Promise.all([p1, p2, p3]), а последовательные await одна за другой выполнятся строго по очереди, теряя выгоду от параллельного I/O. Вторая типичная ошибка — забыть try/catch вокруг await: непойманный rejected promise превращается в unhandledRejection, который в новых версиях Node может привести к аварийному завершению процесса. Настройка process.on('unhandledRejection', ...) в точке входа приложения — не избыточная предосторожность, а страховка от того, что один забытый catch где-то в глубине кода уронит весь сервер целиком.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: не блокируй event loop; await + try/catch на каждом I/O.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши file I/O на async/await с try/catch
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. File watcher: логирует изменения notes.json, останавливается на SIGINT
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Промисификация: const readFile = promisify(fs.readFile) — для понимания legacy
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Обработка unhandledRejection и uncaughtException в entry point
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Параллельное чтение 3 файлов через Promise.all
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Замер: sync readFileSync vs async на 10 файлах — почувствуй блокировку
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Нет callback hell — только async/await\n- [ ] Watcher корректно останавливается (SIGINT)\n- [ ] try/catch вокруг await

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Перепиши file I/O на async/await с try/catch
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. File watcher: логирует изменения notes.json, останавливается на SIGINT
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Промисификация: const readFile = promisify(fs.readFile) — для понимания legacy
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-19/git commit -m \"week 19 day 128: async file watcher and error handling\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Забытый await — Promise вместо данных
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Синхронный fs.readFileSync в сервере — блокирует event loop
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 129 (Ср): Express — REST API основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Express Notes API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Express — минималистичный HTTP-фреймворк поверх Node http. app.get/post/put/delete маппят метод + путь на handler. req.params — path params, req.query — query string, req.body — JSON после express.json() middleware. Без body parser req.body будет undefined — классическая ловушка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        HTTP semantics: 200 OK, 201 Created, 204 No Content (DELETE без body), 400 Bad Request, 404 Not Found. Раздели app.js (конфигурация, middleware, routes) и server.js (listen) — app экспортируется для тестов. nodemon автоперезапускает в dev.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CRUD /api/notes с хранением в JSON-файле — мост к PostgreSQL завтра. Единый формат ответа { data } или { error: { message } } упрощает фронтенд. RESTful URLs: существительные, не глаголы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель Express — конвейер middleware. Каждый входящий запрос проходит по цепочке функций-станций (loggerexpress.json() → маршруты → обработка 404 → обработчик ошибок), и каждая станция может прочитать/изменить запрос, ответить сразу или передать управление дальше через next(). Порядок подключения middleware в коде буквально определяет порядок их выполнения — это не декларативная конфигурация, а императивная последовательность.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Разделение app.js (конфигурация приложения) и server.js (запуск через listen) — не формальность: это тот же принцип тестируемости, что и TestClient в FastAPI на предыдущей неделе — app можно импортировать в тесты и слать в него запросы напрямую, без реального сетевого порта, что делает автотесты (день 133 и практика проекта) быстрыми и надёжными.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение новичков — писать POST-обработчик, обращаться к req.body и получать undefined, не понимая почему: без подключённого express.json() middleware Express не парсит тело запроса автоматически — это осознанное архитектурное решение фреймворка, а не баг. Вторая распространённая ошибка — сваливать все маршруты в один растущий app.js на сотни строк вместо разделения по ресурсам (routes/notes.js, routes/authors.js), что уже на следующей неделе (после появления PostgreSQL) станет неуправляемым. Единый формат ответа ({ data } для успеха, { error: { message } } для ошибки) — небольшая деталь с большим эффектом: фронтенд может написать один универсальный обработчик ответов вместо разбора уникальной формы JSON для каждого отдельного endpoint. HTTP-семантика статусов из практики дня — тоже часть этого контракта: 201 Created сообщает фронтенду «ресурс появился, можно обновить список», а 204 No Content на DELETE явно говорит «операция прошла успешно, но отвечать нечем» — разница, которая имеет значение для клиентского кода, реагирующего на статус, а не только на тело ответа.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: express.json() обязателен; app отдельно от server — тестируемость.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install express, src/app.js, src/server.js
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CRUD /api/notes — хранение в JSON-файле через fs
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. GET /api/notes/:id — 404 если нет (res.status(404).json(...))
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. npm install -D nodemon, script \"dev\": \"nodemon src/server.js\"
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь все методы через curl или Thunder Client
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Единый формат ответа: { data } или { error: { message } }
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] express.json() подключён\n- [ ] RESTful URLs и методы\n- [ ] 201 на POST, 204 на DELETE

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install express, src/app.js, src/server.js
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. CRUD /api/notes — хранение в JSON-файле через fs
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. GET /api/notes/:id — 404 если нет (res.status(404).json(...))
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-19/git commit -m \"week 19 day 129: Express CRUD notes in-memory JSON\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • POST без body parser — req.body undefined
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Один огромный app.js — разбей на routes
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 130 (Чт): Middleware, валидация, ошибки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Express Notes API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Middleware в Express — функции (req, res, next) в цепочке. Порядок критичен: logger → express.json() → routes → 404 handler → error middleware (4 аргумента: err, req, res, next). next() передаёт управление дальше; next(err) — в error handler.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Zod валидирует body с TypeScript inference: title min 1 символ, body optional. При ошибке — 400 с zodError.flatten(). Centralized error handler возвращает JSON { error: { code, message } } — единый контракт для клиента. morgan логирует HTTP-запросы в dev.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        404 handler для неизвестных routes — последний middleware перед error handler. Custom logger с duration (Date.now до/после) дополняет morgan. Error middleware без 4 параметров Express не распознает — не вызовется.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель порядка middleware — фильтры кофемашины: если поставить фильтр валидации до того, как вода (тело запроса) прошла через парсер (express.json()), фильтр получит пустоту вместо данных и либо пропустит мусор, либо сломается непредсказуемо. Порядок регистрации middleware в Express — это не стилистическое предпочтение, а часть логики приложения: express.json() обязан идти раньше любого middleware, читающего req.body.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Формат централизованной ошибки { error: { code, message } }, который ты вводишь сегодня, — не изобретение с нуля: это прямая параллель HTTPException + response_model из FastAPI на прошлой неделе. Оба стека решают одну и ту же задачу — дать фронтенду предсказуемый, единообразный контракт ошибок независимо от того, какой именно endpoint и какая причина сбоя. Сравнение этих двух подходов в конце недели наглядно покажет, что архитектурная идея важнее конкретного синтаксиса фреймворка.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое и коварное заблуждение — думать, что любую функцию с (req, res, next) можно превратить в обработчик ошибок, если просто вызвать её после остальных. Express распознаёт error-middleware исключительно по количеству аргументов — ровно четыре: (err, req, res, next). Функция с тремя параметрами, даже поставленная в конце цепочки, никогда не будет вызвана как error handler — это тихая, трудноуловимая ошибка, потому что сам код не падает, просто ошибки остаются необработанными. Вторая ошибка — забыть вызвать next(err) в обычном middleware при перехвате исключения, из-за чего запрос «зависает» без ответа клиенту. morgan в режиме 'dev' дополняет ручной логгер: он выводит метод, путь, статус-код и время ответа компактной цветной строкой, что удобно при локальной разработке, тогда как 'combined'-формат ближе к тому, что нужно собирать в продакшен-логах.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: порядок middleware; Zod на входе, error handler на выходе цепочки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Logger middleware: method, url, duration (Date.now до/после)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Zod schema для Note: title min 1, body optional string
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Centralized error handler — JSON { error: { code, message } }
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. 400 при validation error с деталями Zod (zodError.flatten())
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. 404 handler для неизвестных routes (app.use((req,res) => ...))
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. morgan 'dev' format в development
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Все ошибки проходят через error middleware\n- [ ] Zod на POST и PUT\n- [ ] morgan или custom logger

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Logger middleware: method, url, duration (Date.now до/после)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Zod schema для Note: title min 1, body optional string
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Centralized error handler — JSON { error: { code, message } }
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-19/git commit -m \"week 19 day 130: Zod validation and error middleware\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Забытый next(err) — зависший request
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Error middleware без 4 параметров — не вызывается
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 131 (Пт): Express + PostgreSQL

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Express Notes API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        node-postgres (pg) — драйвер PostgreSQL для Node. Pool переиспользует соединения под нагрузкой; new Client() на каждый запрос — антипаттерн. pool.query('SELECT * FROM notes WHERE id = $1', [id]) — placeholders $1, $2 защищают от SQL injection.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DATABASE_URL=postgresql://user:pass@host:5432/db из .env через dotenv. Prisma — ORM-альтернатива (обзор); на этой неделе raw pg учит SQL и placeholders. Graceful shutdown: pool.end() на SIGTERM.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Перепиши notes API с JSON-файла на таблицу notes(id, title, body, created_at). schema.sql + migrate script. Все запросы только через pool.query с массивом параметров — template strings в SQL запрещены.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель Pool — парковка с несколькими свободными местами вместо строительства нового гаража под каждую машину. new Client() на каждый запрос означает установление нового TCP-соединения к PostgreSQL при каждом HTTP-запросе — дорого и не масштабируется под нагрузкой. Pool заранее держит несколько открытых соединений, выдаёт свободное на время запроса и возвращает обратно, а не закрывает — ровно тот же принцип переиспользования ресурсов, что и session-per-request в SQLAlchemy на прошлой неделе.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Плейсхолдеры $1, $2 в node-postgres — это тот же самый принцип безопасности, который ты уже видел как ? в sqlite3 (неделя 16) и %s в psycopg2 (неделя 17): разный синтаксис, одна и та же идея — данные передаются драйверу отдельно от текста запроса, и СУБД никогда не путает пользовательский ввод с кодом SQL. Три экосистемы, три синтаксиса, один принцип — это стоит запомнить как универсальное правило, а не деталь конкретной библиотеки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — считать, что «ручная» экранизация кавычек в строке перед вставкой в SQL через шаблонный литерал (`WHERE name = '${escaped}'`) достаточно безопасна. Единственный надёжный способ защититься от SQL injection — параметризованные запросы; любая самодельная санитизация рано или поздно пропустит edge case (Unicode-трюки, вложенные кавычки, null-байты). Вторая ошибка — не закрывать Pool при остановке приложения (pool.end() на SIGTERM), из-за чего процесс может зависать при попытке штатной остановки, а открытые соединения — накапливаться на стороне PostgreSQL. Перенос notes API с JSON-файла на настоящую таблицу — не просто смена хранилища: он заставляет явно продумать схему (id, title, body, created_at) и написать schema.sql вместо неявной структуры JS-объекта, что дисциплинирует так же, как проектирование схемы «Библиотека» на прошлой неделе.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: Pool, не Client; $1 placeholders — единственный безопасный способ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install pg dotenv
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. src/db/pool.js — Pool из DATABASE_URL, тест SELECT NOW()
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Перепиши notes API на таблицу notes(id, title, body, created_at)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. schema.sql + scripts/migrate.js или npm run db:migrate
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. seed.sql с 5 тестовыми заметками
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Все запросы через pool.query('... WHERE id = $1', [id])
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Pool, не Client на каждый запрос\n- [ ] Параметризованные запросы ($1, $2)\n- [ ] dotenv, .env.example

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install pg dotenv
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. src/db/pool.js — Pool из DATABASE_URL, тест SELECT NOW()
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Перепиши notes API на таблицу notes(id, title, body, created_at)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-19/git commit -m \"week 19 day 131: Express notes with PostgreSQL pool\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • SQL injection через template strings — только placeholders
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Pool не закрывается при shutdown — graceful exit
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 132 (Сб): Структура проекта и роутеры

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Express Notes API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Express Router модульно группирует маршруты: notes.routes.js монтируется с prefix /api/notes. Layered architecture: routes (тонкие) → controllers (HTTP) → services (бизнес-логика) → db (SQL). Бизнес-логика в route handler не тестируется — вынеси в service.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        dotenv загружает secrets из .env; NODE_ENV=development|production меняет поведение (morgan 'dev' vs 'combined'). Health check GET /api/health возвращает { status, db: 'ok'|'down', uptime } — нужен для Docker и мониторинга. 503 если БД недоступна.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Graceful shutdown: SIGTERM → server.close()pool.end(). package-lock.json в git — воспроизводимые сборки. README описывает слои папок — onboarding нового разработчика.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель layered-архитектуры — песочные часы: HTTP-специфичные детали (заголовки, статусы, парсинг запроса) сужаются к чистой бизнес-логике в узком горлышке (service), а затем снова расширяются к деталям хранения данных (db). Каждый слой знает только о соседнем: controller не знает, как устроен SQL-запрос внутри service, а service не знает, что вызвавший его код — это HTTP-запрос, а не, например, cron-задача или CLI-команда.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Это разделение — не Node-специфичная причуда: это буквально та же архитектура routers → crud → models → db, которую ты собрал в FastAPI на прошлой неделе, только с другими именами слоёв. Узнавание одного и того же архитектурного паттерна в двух разных языках и фреймворках — куда более ценный навык, чем запоминание синтаксиса одного конкретного стека, и именно это делает тебя способным быстро освоить третий, четвёртый фреймворк в будущем.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — писать бизнес-логику прямо внутри route-обработчика «раз уж всё равно там нужен доступ к req и res». Логика, зашитая в controller, не может быть протестирована без поднятия HTTP-сервера и не может быть переиспользована, если та же операция понадобится, например, из cron-задачи. Вторая ошибка — делать health check, который слепо возвращает 200 OK, не проверяя реальную доступность БД: оркестраторы вроде Docker или Kubernetes используют health check, чтобы решить, направлять ли трафик на этот инстанс, и «фальшиво здоровый» сервис без реального подключения к БД будет продолжать получать запросы, которые обречены на ошибку. Graceful shutdown (SIGTERMserver.close()pool.end()) — финальный штрих той же дисциплины: сервер должен успеть корректно завершить уже начатые запросы и закрыть соединения с БД перед остановкой, а не обрубать их резко, теряя данные в процессе.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: routes тонкие, logic в services; health check — контракт с инфраструктурой.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Структура: src/routes/, controllers/, services/, db/pool.js
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Вынеси логику из routes в controller/service
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. GET /api/health{ status, db: 'ok'|'down', uptime }
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Router notes.routes.js → controller notes.controller.js → service notes.service.js
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Graceful shutdown: SIGTERM → close server → pool.end()
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. README: структура папок с описанием слоёв
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Routes тонкие — только маршрутизация\n- [ ] Service переиспользуется из controller\n- [ ] health check возвращает 503 если DB down

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Структура: src/routes/, controllers/, services/, db/pool.js
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Вынеси логику из routes в controller/service
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. GET /api/health{ status, db: 'ok'|'down', uptime }
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-19/git commit -m \"week 19 day 132: layered architecture and health check\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Бизнес-логика в route handler — не тестируется
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Циклические импорты между modules
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 133 (Вс): Ревью Node.js и сравнение с FastAPI

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Express Notes API

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью недели — сравнение двух backend-стеков, которые ты теперь знаешь. FastAPI: автодоки, Pydantic, async, Python ecosystem. Express: минимализм, npm, один язык с React. Для I/O-bound оба отличны; CPU-bound тяжёлая работа чаще уходит в Python или отдельный worker.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        npm scripts best practices: start (production), dev (nodemon), test, db:migrate. Postman collection — демо и ручное QA. Skeleton auth.routes.js — мост к неделе 20. npm audit показывает уязвимости в зависимостях.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Сравнительная таблица FastAPI vs Express по 10 критериям учит аргументировать выбор стека. Express Notes API — parity с Library REST API недели 18: те же статусы, формат ошибок, layered structure. Тег week-19-done.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель для сравнения стеков — две разные клавиатуры, подключённые к одному и тому же роялю. FastAPI и Express предлагают разную эргономику (типизация из коробки против гибкости без неё, автогенерация Swagger против ручной настройки, async Python против нативно-асинхронного JS), но производят одну и ту же «музыку» — REST-ресурсы, HTTP-статусы, JSON-контракты. Разработчик, освоивший оба, видит сквозь синтаксис общую архитектуру.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Умение аргументированно сравнить два стека по конкретным критериям (типизация, экосистема библиотек, производительность под нагрузкой, порог входа для команды, зрелость инструментов) — это именно тот навык, который проверяют на технических интервью вопросом «почему вы выбрали X, а не Y», и именно поэтому сравнительная таблица — не формальность, а тренировка аргументации, которая пригодится за пределами учебного проекта.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Частое заблуждение — искать единственно «правильный» стек и считать все остальные хуже. На практике выбор между FastAPI и Express в реальной команде почти никогда не решается голым сравнением фреймворков: он зависит от опыта команды, существующего кода, экосистемы (например, ML/data-задачи почти всегда тянут к Python), требований к производительности и скорости найма разработчиков. Skeleton auth.routes.js с заглушками — не проходной пункт практики, а прямой мост к теме аутентификации, которую ты будешь реализовывать уже на следующей неделе, причём в обоих стеках параллельно. npm audit в практике дня — ещё одна привычка, которая пригодится за пределами курса: открытый исходный код зависимостей означает и открытые уязвимости, и регулярная проверка (а не разовая на старте проекта) — часть базовой гигиены production-приложения.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: Express и FastAPI решают одну задачу разными инструментами — выбор по команде и экосистеме.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сравнительная таблица: FastAPI (нед.18) vs Express — 10 критериев в docs/compare.md
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Postman collection для Express API — export JSON
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. README с curl примерами для всех endpoints
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Skeleton: src/routes/auth.routes.js с заглушками register/login
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. npm audit — отчёт об уязвимостях
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Финальный smoke test: CRUD notes через API
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] README полный (install, env, run, test)\n- [ ] Сравнительная таблица в docs\n- [ ] npm start и npm run dev работают

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Сравнительная таблица: FastAPI (нед.18) vs Express — 10 критериев в docs/compare.md
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Postman collection для Express API — export JSON
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. README с curl примерами для всех endpoints
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-19/git commit -m \"week 19 day 133: docs, Postman, auth skeleton\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поставь тег: git tag week-19-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Express Notes API с PostgreSQL. Спецификация: docs/projects.md — неделя 19.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        week-19/\n├── src/\n│   ├── app.js\n│   ├── server.js\n│   ├── routes/\n│   ├── controllers/\n│   ├── services/\n│   ├── db/\n│   └── middleware/\n├── schema.sql\n├── docs/\n│   ├── postman-collection.json\n│   └── compare.md\n├── package.json\n├── .env.example\n└── README.md\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Full CRUD /api/notes
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Zod validation, error middleware, request logging (morgan)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Layered architecture: routes → controllers → services → db
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. PostgreSQL + migrations + seed
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Health check, graceful shutdown, Postman collection
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Production-like структура папок
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Все SQL через pool.query с placeholders
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Graceful shutdown (SIGTERM) закрывает pool
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Health endpoint возвращает статус БД
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Postman collection покрывает все endpoints
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Стиль API согласован с FastAPI проектом недели 18 (статусы, формат ошибок)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Тег week-19-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Node vs Browser JS — 3 главных отличия?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что делает middleware next()?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Зачем connection pool вместо одного client?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как валидировать body в Express?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • ESM vs CommonJS — что выбрал и почему?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Express Notes API** в `learning-log/week-19/`, осмысленная Git-история, тег `week-19-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nNode.js + Express layered API\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-19-day-127", "label": "День 127 (Пн): Node.js — среда и модули"}, {"id": "week-19-day-128", "label": "День 128 (Вт): Асинхронность в Node"}, {"id": "week-19-day-129", "label": "День 129 (Ср): Express — REST API основы"}, {"id": "week-19-day-130", "label": "День 130 (Чт): Middleware, валидация, ошибки"}, {"id": "week-19-day-131", "label": "День 131 (Пт): Express + PostgreSQL"}, {"id": "week-19-day-132", "label": "День 132 (Сб): Структура проекта и роутеры"}, {"id": "week-19-day-133", "label": "День 133 (Вс): Ревью Node.js и сравнение с FastAPI"}, {"id": "week-19-project", "label": "Проект недели"}, {"id": "week-19-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-19-review", "label": "Проверь себя"}], "text": "Неделя 19: Node.js + Express REST API Цель недели: построить REST API на JavaScript в среде Node.js с Express и PostgreSQL. Литература: Node.js Docs , Express Guide , node-postgres Проект недели: Express Notes API — layered Express API, Zod, PostgreSQL, Postman collection. Git: папка learning-log/week-19/ , ветки feature/routes , feature/pg ; тег week-19-done . День 127 (Пн): Node.js — среда и модули Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Express Notes API Теория Node.js — среда выполнения JavaScript вне браузера. Нет DOM и window , зато есть process , встроенные модули и npm-экосистема. Backend на Node разделяет язык с фронтендом — один TypeScript/JavaScript на обе стороны, но ru…"} \ No newline at end of file diff --git a/docs/weeks/20.json b/docs/weeks/20.json index 36a1409..61c8e87 100644 --- a/docs/weeks/20.json +++ b/docs/weeks/20.json @@ -1 +1 @@ -{"id": "week-20", "title": "Auth & tests", "fullTitle": "Неделя 20: Auth, безопасность, тестирование", "html": "

                                                                                                                                                                                                                        Неделя 20: Auth, безопасность, тестирование

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: реализовать JWT-аутентификацию, изучить OWASP и написать базовые тесты (Vitest + pytest).\nЛитература: JWT.io, OWASP Top 10, Vitest, pytest\nПроект недели: Secure Notes — JWT auth, bcrypt, rate limit, React client, pytest + Vitest.\nGit: папка learning-log/week-20/, отдельные коммиты backend/frontend; тег week-20-done.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 134 (Пн): Аутентификация и хеширование паролей

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Secure Notes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Authentication отвечает на вопрос «кто ты?» — проверка личности (логин/пароль). Authorization — «что тебе можно?» — права на ресурсы. Не путай: успешный login не означает доступ ко всем endpoints. Пароли никогда не хранятся в plain text, даже в dev-базе.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        bcrypt (Node) и passlib с bcrypt (Python) — adaptive hashing с встроенным salt. Salt rounds 10–12 — баланс безопасность/скорость. При register: validate email → hash(password, 12) → store password_hash. При login: compare(plain, hash). SHA256 без salt уязвим к rainbow tables.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Registration flow: дубликат email → 409 Conflict. Login: неверный пароль → 401 Unauthorized с generic message «Invalid credentials» — не раскрывай, существует ли email. Пароль не логируй и не возвращай в JSON response.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: hash + salt через bcrypt; одинаковые сообщения об ошибке login — против enumeration.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Таблица users(id, email UNIQUE, password_hash, created_at)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Express: POST /auth/register, POST /auth/login
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. bcrypt.hash(password, 12) при register, bcrypt.compare() при login
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. FastAPI параллельно (или выбери один стек): passlib[bcrypt], CryptContext
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Дубликат email → 409 Conflict
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Неверный пароль → 401 Unauthorized
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Пароль никогда не логируется и не возвращается в JSON\n- [ ] Дубликат email → 409\n- [ ] Неверный пароль → 401 (не 404)

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Таблица users(id, email UNIQUE, password_hash, created_at)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Express: POST /auth/register, POST /auth/login
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. bcrypt.hash(password, 12) при register, bcrypt.compare() при login
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m \"week 20 day 134: register login bcrypt\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • SHA256 без salt для паролей — уязвимо к rainbow tables
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Разные сообщения для «user not found» и «wrong password» — information leak
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 135 (Вт): JWT — выдача и проверка токенов

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Secure Notes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        JWT (JSON Web Token) — компактный способ передавать claims между клиентом и сервером. Структура: header.payload.signature. Подпись (HMAC SHA256) гарантирует целостность; payload base64-decodable — не клади пароли и PII. Стандарт передачи: Authorization: Bearer <token>.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Access token TTL 15min–1h; refresh token — отдельный долгоживущий механизм (обзор). JWT_SECRET в .env — минимум 32 случайных байта; при утечке — rotate немедленно. Payload: sub (user id), exp, iat. Явно указывай algorithm: 'HS256' — алгоритм none — уязвимость.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Middleware authenticateToken verify JWT и кладёт req.user = { id, email }. Protected routes читают user_id из token, не из body/query — иначе IDOR. Expired token → 401. Тест с TTL 1 секунда проверяет expiration.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: JWT — подписанный контракт, не шифрование; user_id только из verified token.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Login возвращает { access_token, token_type: \"bearer\", expires_in }
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Middleware authenticateToken — verify JWT, req.user = { id, email }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Protected: GET /api/notes только с valid token
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. 401 без token, 403 при доступе к чужим данным (user_id из token)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Expired token test — измени TTL на 1 сек для проверки
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Явно укажи algorithm: algorithm: 'HS256'
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] JWT_SECRET в .env, не в коде\n- [ ] Expired token → 401\n- [ ] user_id из token, не из body/query

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Login возвращает { access_token, token_type: \"bearer\", expires_in }
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Middleware authenticateToken — verify JWT, req.user = { id, email }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Protected: GET /api/notes только с valid token
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m \"week 20 day 135: JWT middleware and protected routes\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Алгоритм none — всегда указывай algorithm explicitly
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Sensitive data в JWT payload — payload base64-decodable
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 136 (Ср): OWASP Top 10 — практическая защита

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Secure Notes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        OWASP Top 10 — карта самых частых уязвимостей веб-приложений. Ты уже закрываешь injection parameterized queries (нед. 17–19). Broken authentication — слабые пароли, утечка session. XSS — неэкранированный user-generated HTML; escape output, DOMPurify для rich text.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Helmet.js выставляет security headers: X-Content-Type-Options, X-Frame-Options, CSP basics. express-rate-limit на /auth/login: 5 попыток / 15 мин per IP → 429 Too Many Requests — защита от brute-force. CORS: явный whitelist origins; origin: '*' с credentials — небезопасно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Аудит: .env в .gitignore, .env.example без секретов, проверь git log на утечки. security-audit.md с чеклистом 10 пунктов — deliverable недели. CORS в dev: allow только http://localhost:5173.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: безопасность — слои: hash, JWT, rate limit, headers, CORS, audit.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Rate limit на /auth/login: 5 попыток / 15 мин per IP
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. helmet() в Express; FastAPI — security headers middleware (обзор)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Аудит API: чеклист OWASP 10 пунктов → security-audit.md
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. .env в .gitignore, .env.example без реальных секретов
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь: нет секретов в git log (git log -p | grep SECRET)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. CORS: allow только http://localhost:5173 в dev
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Rate limiting работает (429 Too Many Requests)\n- [ ] Helmet headers в response (проверь curl -I)\n- [ ] Чеклист OWASP заполнен в security-audit.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Rate limit на /auth/login: 5 попыток / 15 мин per IP
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. helmet() в Express; FastAPI — security headers middleware (обзор)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Аудит API: чеклист OWASP 10 пунктов → security-audit.md
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m \"week 20 day 136: OWASP audit rate limit helmet\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • CORS origin: '*' с credentials — небезопасно
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Секреты в git history — rotate keys если утекли
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 137 (Чт): Тестирование backend — pytest

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Secure Notes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Backend-тесты ловят регрессии в auth и authorization. pytest + FastAPI TestClient или supertest для Express — HTTP без реального порта. Fixtures: create_user(), auth_headers(token). Test DB изолирована: отдельная schema или rollback per test — никогда production.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Arrange-Act-Assert в каждом тесте. Покрой: register success, duplicate 409, wrong password 401, protected 401 без token, 200 с token, user A не видит notes user B. conftest.py — shared setup. pytest --cov=app показывает пробелы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты не должны зависеть от порядка выполнения. Hardcoded JWT secret в тестах должен совпадать с app config. ≥ 10 тестов — минимум для Secure Notes. Flaky tests из shared DB без cleanup — исправь до merge.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: тестируй auth, 403 cross-user и 401 без token — не только happy path.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Тесты auth: register success, duplicate email 409, login, wrong password 401
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Fixture: test user + valid token в Authorization header
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Protected route: 401 без token, 200 с token
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. CRUD notes per user — user A не видит notes user B
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. ≥ 10 pytest тестов для выбранного backend (FastAPI или Express через supertest)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. conftest.py с test database и cleanup
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] pytest все зелёные\n- [ ] Тесты не зависят от порядка выполнения\n- [ ] conftest.py с test database

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Тесты auth: register success, duplicate email 409, login, wrong password 401
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Fixture: test user + valid token в Authorization header
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Protected route: 401 без token, 200 с token
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m \"week 20 day 137: pytest auth and notes tests\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Тесты на shared DB без cleanup — flaky tests
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Hardcoded JWT secret в тестах отличается от app — 401 везде
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 138 (Пт): Тестирование frontend — Vitest

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Secure Notes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Vitest — test runner, нативный для Vite-проектов, API совместим с Jest. React Testing Library (RTL) тестирует поведение с точки зрения пользователя: getByRole, getByLabelText, не getByClassName. userEvent симулирует реальные клики и ввод с клавиатуры.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Mock fetch через vi.fn() или global.fetch = vi.fn().mockResolvedValue(...) изолирует компоненты от API. Тестируй: Login submit шлёт credentials, ProtectedRoute редиректит без token, NotesList рендерит mock data, login 401 показывает ошибку. vi.mock() для модулей.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        ≥ 8 component tests. vitest run в CI. Тестирование internal state вместо visible behavior — хрупкие тесты. Cleanup mocks в afterEach — иначе тесты влияют друг на друга.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: RTL — «как пользователь видит»; mock fetch, не implementation details.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom @testing-library/user-event
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Тест: Login form — submit вызывает API с email/password
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Тест: Protected route redirect на /login без token
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Mock API: register success, login 401 показывает ошибку
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Тест NotesList — рендерит заметки из mock response
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. npm test / vitest run в package.json scripts
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] vitest run проходит\n- [ ] Тесты ищут по role/label, не по className\n- [ ] ≥ 8 unit/component тестов

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom @testing-library/user-event
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Тест: Login form — submit вызывает API с email/password
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Тест: Protected route redirect на /login без token
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m \"week 20 day 138: Vitest auth and notes components\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Тестирование state вместо behavior — хрупкие тесты
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Забытый mock cleanup — тесты влияют друг на друга
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 139 (Сб): Интеграция auth frontend + backend

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Secure Notes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Full-stack auth связывает JWT backend с React frontend. Token storage: localStorage прост, но уязвим к XSS; httpOnly cookie безопаснее, сложнее с CORS. Для учебного проекта localStorage + CSP + sanitize input — приемлемо; задокументируй trade-off в README.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        AuthContext: user, token, login, logout, isLoading. api.ts wrapper подставляет Authorization: Bearer и на 401 очищает token + redirect /login. React Router <ProtectedRoute> оборачивает private pages. Token не в URL query string — утечёт в logs и history.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Full flow: register → login → create note → logout → login → note visible. User A не видит notes User B — проверь вручную и тестами. Axios interceptors или fetch wrapper — один вход для всех API calls.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: auth flow end-to-end — контракт между Context, api wrapper и protected routes.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. React (Vite + TS): Login/Register pages с валидацией форм
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. AuthContext + useAuth() hook
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. api.ts wrapper — подставляет Bearer token, обрабатывает 401
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Protected routes — redirect /login если не авторизован
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Logout очищает token и context, redirect на login
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Full flow manual test: register → login → create note → logout → login again
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Full flow: register → login → access protected → logout\n- [ ] 401 от API → redirect login\n- [ ] Token не в URL query string

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. React (Vite + TS): Login/Register pages с валидацией форм
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. AuthContext + useAuth() hook
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. api.ts wrapper — подставляет Bearer token, обрабатывает 401
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m \"week 20 day 139: React auth integration\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • XSS + localStorage token — кража token (mitigate: CSP, sanitize input)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Token без expiration check на клиенте — плохой UX при expired
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 140 (Вс): Ревью безопасности и CI

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Secure Notes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CI автоматизирует проверку качества на каждый push. GitHub Actions: matrix jobs для backend (pytest) и frontend (vitest run). Зелёный CI — сигнал, что main mergeable. Branch protection с require CI — best practice для команд (обзор).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        npm audit и pip audit сканируют known vulnerabilities в зависимостях. Critical без комментария или плана фикса — красный флаг для портфолио. Semgrep — static analysis (обзор). Sequence diagram auth flow в README объясняет архитектуру ревьюеру.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Финальный security review по OWASP чеклисту. Обнови .env.example для backend и frontend. Smoke test checklist в README. Тег week-20-done — Secure Notes готов как шаблон для недель 21–22.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: CI + security audit — часть Definition of Done, не «после деплоя».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. .github/workflows/ci.yml: pytest + vitest run на push
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. npm audit и pip audit — отчёт в security-audit.md
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Документируй auth flow: sequence diagram в README
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Финальный security review по OWASP чеклисту
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Обнови .env.example для backend и frontend
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Smoke test checklist в README
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] CI workflow файл в .github/workflows/\n- [ ] npm audit — нет critical без комментария\n- [ ] Auth flow задокументирован

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. .github/workflows/ci.yml: pytest + vitest run на push
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. npm audit и pip audit — отчёт в security-audit.md
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Документируй auth flow: sequence diagram в README
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m \"week 20 day 140: CI workflow and security docs\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поставь тег: git tag week-20-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Secure Notes API + React Client. Спецификация: docs/projects.md — неделя 20.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Стек

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Backend: Express или FastAPI — register, login, JWT, CRUD notes per user
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Security: bcrypt/passlib, rate limit на login, helmet/CORS
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Frontend: React + TypeScript — auth pages, protected dashboard, notes CRUD
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Tests: pytest ≥ 10, Vitest ≥ 8
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • CI: GitHub Actions green on push
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Регистрация и логин с JWT access token
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Notes привязаны к user_id из token
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. User A не может читать/менять notes User B → 403
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. React: AuthContext, protected routes, API wrapper
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. security-audit.md с OWASP чеклистом
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Пароли hashed, JWT в Authorization: Bearer header
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Rate limiting на /auth/login
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Frontend + backend тесты в CI
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • OWASP чеклист пройден и задокументирован
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Full auth flow работает end-to-end в браузере
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • README: env vars, run backend, run frontend, run tests
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Тег week-20-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • JWT vs session cookie — плюсы и минусы?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как защититься от SQL injection и XSS?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Зачем rate limiting на login?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что тестирует React Testing Library?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что делать если JWT secret утёк в git?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Secure Notes** в `learning-log/week-20/`, осмысленная Git-история, тег `week-20-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nJWT auth, безопасность, тесты\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-20-day-134", "label": "День 134 (Пн): Аутентификация и хеширование паролей"}, {"id": "week-20-day-135", "label": "День 135 (Вт): JWT — выдача и проверка токенов"}, {"id": "week-20-day-136", "label": "День 136 (Ср): OWASP Top 10 — практическая защита"}, {"id": "week-20-day-137", "label": "День 137 (Чт): Тестирование backend — pytest"}, {"id": "week-20-day-138", "label": "День 138 (Пт): Тестирование frontend — Vitest"}, {"id": "week-20-day-139", "label": "День 139 (Сб): Интеграция auth frontend + backend"}, {"id": "week-20-day-140", "label": "День 140 (Вс): Ревью безопасности и CI"}, {"id": "week-20-project", "label": "Проект недели"}, {"id": "week-20-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-20-review", "label": "Проверь себя"}], "text": "Неделя 20: Auth, безопасность, тестирование Цель недели: реализовать JWT-аутентификацию, изучить OWASP и написать базовые тесты (Vitest + pytest). Литература: JWT.io , OWASP Top 10 , Vitest , pytest Проект недели: Secure Notes — JWT auth, bcrypt, rate limit, React client, pytest + Vitest. Git: папка learning-log/week-20/ , отдельные коммиты backend/frontend; тег week-20-done . День 134 (Пн): Аутентификация и хеширование паролей Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Secure Notes Теория Authentication отвечает на вопрос «кто ты?» — проверка личности (логин/пароль). Authorization — «что тебе можно?» — права на ресурсы. Не путай: успешный login не означает доступ ко всем endpoints. …"} \ No newline at end of file +{"id": "week-20", "title": "Auth & tests", "fullTitle": "Неделя 20: Auth, безопасность, тестирование", "html": "

                                                                                                                                                                                                                        Неделя 20: Auth, безопасность, тестирование

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: реализовать JWT-аутентификацию, изучить OWASP и написать базовые тесты (Vitest + pytest).\nЛитература: JWT.io, OWASP Top 10, Vitest, pytest\nПроект недели: Secure Notes — JWT auth, bcrypt, rate limit, React client, pytest + Vitest.\nGit: папка learning-log/week-20/, отдельные коммиты backend/frontend; тег week-20-done.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 134 (Пн): Аутентификация и хеширование паролей

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Secure Notes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Authentication отвечает на вопрос «кто ты?» — проверка личности (логин/пароль). Authorization — «что тебе можно?» — права на ресурсы. Не путай: успешный login не означает доступ ко всем endpoints. Пароли никогда не хранятся в plain text, даже в dev-базе.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        bcrypt (Node) и passlib с bcrypt (Python) — adaptive hashing с встроенным salt. Salt rounds 10–12 — баланс безопасность/скорость. При register: validate email → hash(password, 12) → store password_hash. При login: compare(plain, hash). SHA256 без salt уязвим к rainbow tables.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Registration flow: дубликат email → 409 Conflict. Login: неверный пароль → 401 Unauthorized с generic message «Invalid credentials» — не раскрывай, существует ли email. Пароль не логируй и не возвращай в JSON response.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: хеш пароля — это цифровой отпечаток, а не сейф с ключом. Ты не «открываешь» hash обратно в пароль — bcrypt при login заново хеширует введённый пароль с тем же salt и сравнивает отпечатки. Это принципиально отличает hashing от encryption, где данные можно расшифровать зная ключ. Для junior backend-роли эта тема — почти гарантированный вопрос на собеседовании: «как ты хранишь пароли?» — и неправильный ответ («шифрую AES») сразу выдаёт незрелость. На практике каждая компания, где есть пользователи, должна закрыть этот вопрос в первый день продакшена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Классический пример цены ошибки — утечка LinkedIn 2012 года: пароли хранились как unsalted SHA1, и после взлома миллионы паролей были восстановлены за часы перебором по rainbow tables. Частое заблуждение новичков — «добавлю к паролю секретную строку и захеширую SHA256, этого достаточно» — но без cost-фактора (salt rounds) современные GPU перебирают миллиарды SHA256-хешей в секунду, а bcrypt намеренно медленный и настраиваемый. Именно этот механизм регистрации ты сегодня реализуешь в Secure Notes, и тот же код позже переиспользуешь в DevHub capstone (неделя 22, день 151) — прочный фундамент экономит часы отладки в финале роадмапа.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена важна и обратная сторона: слишком высокий cost factor (например, 15+ раундов) замедляет login до заметных пользователю секунд и создаёт нагрузку на CPU при пиковой регистрации — поэтому 10–12 раундов остаётся индустриальным стандартом, а не произвольным числом. Держи это в голове при код-ревью чужого auth-кода: cost factor — не «чем больше, тем безопаснее», а сознательный компромисс между защитой и latency бюджетом сервиса.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: hash + salt через bcrypt; одинаковые сообщения об ошибке login — против enumeration.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Таблица users(id, email UNIQUE, password_hash, created_at)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Express: POST /auth/register, POST /auth/login
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. bcrypt.hash(password, 12) при register, bcrypt.compare() при login
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. FastAPI параллельно (или выбери один стек): passlib[bcrypt], CryptContext
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Дубликат email → 409 Conflict
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Неверный пароль → 401 Unauthorized
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Пароль никогда не логируется и не возвращается в JSON\n- [ ] Дубликат email → 409\n- [ ] Неверный пароль → 401 (не 404)

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Таблица users(id, email UNIQUE, password_hash, created_at)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Express: POST /auth/register, POST /auth/login
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. bcrypt.hash(password, 12) при register, bcrypt.compare() при login
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m \"week 20 day 134: register login bcrypt\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • SHA256 без salt для паролей — уязвимо к rainbow tables
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Разные сообщения для «user not found» и «wrong password» — information leak
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 135 (Вт): JWT — выдача и проверка токенов

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Secure Notes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        JWT (JSON Web Token) — компактный способ передавать claims между клиентом и сервером. Структура: header.payload.signature. Подпись (HMAC SHA256) гарантирует целостность; payload base64-decodable — не клади пароли и PII. Стандарт передачи: Authorization: Bearer <token>.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Access token TTL 15min–1h; refresh token — отдельный долгоживущий механизм (обзор). JWT_SECRET в .env — минимум 32 случайных байта; при утечке — rotate немедленно. Payload: sub (user id), exp, iat. Явно указывай algorithm: 'HS256' — алгоритм none — уязвимость.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Middleware authenticateToken verify JWT и кладёт req.user = { id, email }. Protected routes читают user_id из token, не из body/query — иначе IDOR. Expired token → 401. Тест с TTL 1 секунда проверяет expiration.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: JWT — это подписанная справка, а не запечатанный конверт. Любой может прочитать payload через base64-decode (проверь на jwt.io), но подделать подпись без секрета невозможно — поэтому в payload никогда не кладут пароли, номера карт или другие секреты, только неконфиденциальные claims вроде user id и роли. На собеседованиях junior-разработчиков часто путают JWT с session cookie: JWT stateless (сервер ничего не хранит, просто проверяет подпись), а session требует хранилища на сервере — эта разница определяет, как система масштабируется горизонтально.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример уязвимости: если backend принимает algorithm: none или не проверяет alg вообще, атакующий может подделать токен с любым payload и получить admin-доступ — это реальная категория уязвимостей, встречавшаяся в популярных JWT-библиотеках. Частое заблуждение — «раз токен подписан, значит зашифрован и безопасен для любых данных» — на деле подпись гарантирует только целостность, не конфиденциальность. Middleware, который ты пишешь сегодня, — это тот же паттерн защищённых маршрутов, который в неделе 22 (день 151) масштабируется на весь DevHub: req.user из verified JWT, а не из тела запроса, закрывает целый класс IDOR-уязвимостей.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена короткий TTL access token (15 минут–1 час) — не паранойя, а ограничение окна атаки: если токен украли через XSS или перехват трафика, он бесполезен уже через час. Полноценный refresh-token механизм с ротацией — тема отдельного, более продвинутого модуля, но важно понимать саму идею уже сейчас: access token — расходный материал, а не постоянный пропуск, который выдаётся один раз и живёт вечно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: JWT — подписанный контракт, не шифрование; user_id только из verified token.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Login возвращает { access_token, token_type: \"bearer\", expires_in }
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Middleware authenticateToken — verify JWT, req.user = { id, email }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Protected: GET /api/notes только с valid token
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. 401 без token, 403 при доступе к чужим данным (user_id из token)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Expired token test — измени TTL на 1 сек для проверки
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Явно укажи algorithm: algorithm: 'HS256'
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] JWT_SECRET в .env, не в коде\n- [ ] Expired token → 401\n- [ ] user_id из token, не из body/query

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Login возвращает { access_token, token_type: \"bearer\", expires_in }
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Middleware authenticateToken — verify JWT, req.user = { id, email }
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Protected: GET /api/notes только с valid token
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m \"week 20 day 135: JWT middleware and protected routes\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Алгоритм none — всегда указывай algorithm explicitly
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Sensitive data в JWT payload — payload base64-decodable
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 136 (Ср): OWASP Top 10 — практическая защита

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Secure Notes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        OWASP Top 10 — карта самых частых уязвимостей веб-приложений. Ты уже закрываешь injection parameterized queries (нед. 17–19). Broken authentication — слабые пароли, утечка session. XSS — неэкранированный user-generated HTML; escape output, DOMPurify для rich text.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Helmet.js выставляет security headers: X-Content-Type-Options, X-Frame-Options, CSP basics. express-rate-limit на /auth/login: 5 попыток / 15 мин per IP → 429 Too Many Requests — защита от brute-force. CORS: явный whitelist origins; origin: '*' с credentials — небезопасно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Аудит: .env в .gitignore, .env.example без секретов, проверь git log на утечки. security-audit.md с чеклистом 10 пунктов — deliverable недели. CORS в dev: allow только http://localhost:5173.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель — думай про безопасность как про слоёный пирог (defense in depth): ни один слой не идеален сам по себе, но вместе hash + JWT + rate limit + headers + CORS перекрывают друг друга. Для junior-позиции знание OWASP Top 10 — не академическое упражнение, а практический чеклист, который спрашивают на security-ориентированных собеседованиях и которым реально пользуются на code review в компаниях с compliance-требованиями (SOC2, PCI DSS).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: без rate limit на /auth/login атакующий может перебрать пароли скриптом за секунды — 5 попыток / 15 минут превращают brute-force в непрактичную атаку. Частое заблуждение начинающих — «у меня маленький pet-проект, кому он нужен» — но боты сканируют весь интернет автоматически, а не выбирают жертву вручную; открытый .env в публичном репозитории находят за минуты. Чеклист security-audit.md, который ты заполняешь сегодня, — прямой прообраз SECURITY.md в DevHub capstone (неделя 22): те же 10 пунктов OWASP, но уже против реального multi-user приложения с репутацией на кону.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена CORS — не разовая настройка, а живой список, который меняется с каждым новым окружением: dev допускает localhost:5173, staging — свой домен, прод — финальный домен фронтенда. Забытая запись в whitelist после деплоя — одна из самых частых причин, почему «API работает в Postman, но не в браузере»: curl и Postman не проверяют CORS вообще, эту проверку делает только браузер, поэтому баг обнаруживается лишь при реальном использовании интерфейса. Держи чеклист OWASP под рукой не как разовое упражнение, а как привычку code review для каждого нового endpoint.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: безопасность — слои: hash, JWT, rate limit, headers, CORS, audit.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Rate limit на /auth/login: 5 попыток / 15 мин per IP
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. helmet() в Express; FastAPI — security headers middleware (обзор)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Аудит API: чеклист OWASP 10 пунктов → security-audit.md
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. .env в .gitignore, .env.example без реальных секретов
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь: нет секретов в git log (git log -p | grep SECRET)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. CORS: allow только http://localhost:5173 в dev
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Rate limiting работает (429 Too Many Requests)\n- [ ] Helmet headers в response (проверь curl -I)\n- [ ] Чеклист OWASP заполнен в security-audit.md

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Rate limit на /auth/login: 5 попыток / 15 мин per IP
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. helmet() в Express; FastAPI — security headers middleware (обзор)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Аудит API: чеклист OWASP 10 пунктов → security-audit.md
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m \"week 20 day 136: OWASP audit rate limit helmet\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • CORS origin: '*' с credentials — небезопасно
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Секреты в git history — rotate keys если утекли
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 137 (Чт): Тестирование backend — pytest

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Secure Notes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Backend-тесты ловят регрессии в auth и authorization. pytest + FastAPI TestClient или supertest для Express — HTTP без реального порта. Fixtures: create_user(), auth_headers(token). Test DB изолирована: отдельная schema или rollback per test — никогда production.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Arrange-Act-Assert в каждом тесте. Покрой: register success, duplicate 409, wrong password 401, protected 401 без token, 200 с token, user A не видит notes user B. conftest.py — shared setup. pytest --cov=app показывает пробелы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты не должны зависеть от порядка выполнения. Hardcoded JWT secret в тестах должен совпадать с app config. ≥ 10 тестов — минимум для Secure Notes. Flaky tests из shared DB без cleanup — исправь до merge.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: тест — это исполняемая спецификация поведения, а не бюрократическая формальность. Arrange-Act-Assert структурирует мышление: подготовь данные, вызови действие, проверь результат — один тест проверяет одну вещь. Для junior-разработчика умение писать тесты на auth и authorization — сигнал зрелости для нанимающего менеджера: код без тестов на security-критичные пути в реальной компании не пройдёт code review.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример пользы: тест «user A не видит notes user B» ловит IDOR-баг ещё до продакшена — без него такая уязвимость обнаруживается только в security-инциденте или пентесте, что стоит репутации и денег. Частое заблуждение новичков — «я протестировал руками через Postman, тестов достаточно» — но ручное тестирование не защищает от регрессий при следующем рефакторинге, а автоматические тесты запускаются на каждый commit. Инфраструктура тестов, которую ты строишь сегодня (fixtures, conftest.py, изоляция БД), — это ровно то, что масштабируется в неделе 22 (день 153) до ≥15 pytest-тестов в CI capstone-проекта.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена тесты выполняют вторую важную функцию — они документируют ожидаемое поведение системы точнее, чем любой комментарий в коде: новый разработчик, зашедший в проект, читает тесты, чтобы понять контракт API, а не гадает по названиям функций. pytest --cov=app показывает не «сколько строк покрыто», а скорее карту слепых зон — мест, куда никто не заглядывал тестами, и именно там чаще всего прячутся баги, которые всплывают в проде. Читай отчёт покрытия критически: 100% покрытия не гарантирует отсутствие багов, если assertions в тестах слабые, но пробелы в покрытии почти всегда указывают на риск.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: тестируй auth, 403 cross-user и 401 без token — не только happy path.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Тесты auth: register success, duplicate email 409, login, wrong password 401
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Fixture: test user + valid token в Authorization header
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Protected route: 401 без token, 200 с token
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. CRUD notes per user — user A не видит notes user B
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. ≥ 10 pytest тестов для выбранного backend (FastAPI или Express через supertest)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. conftest.py с test database и cleanup
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] pytest все зелёные\n- [ ] Тесты не зависят от порядка выполнения\n- [ ] conftest.py с test database

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Тесты auth: register success, duplicate email 409, login, wrong password 401
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Fixture: test user + valid token в Authorization header
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Protected route: 401 без token, 200 с token
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m \"week 20 day 137: pytest auth and notes tests\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Тесты на shared DB без cleanup — flaky tests
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Hardcoded JWT secret в тестах отличается от app — 401 везде
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 138 (Пт): Тестирование frontend — Vitest

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Secure Notes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Vitest — test runner, нативный для Vite-проектов, API совместим с Jest. React Testing Library (RTL) тестирует поведение с точки зрения пользователя: getByRole, getByLabelText, не getByClassName. userEvent симулирует реальные клики и ввод с клавиатуры.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Mock fetch через vi.fn() или global.fetch = vi.fn().mockResolvedValue(...) изолирует компоненты от API. Тестируй: Login submit шлёт credentials, ProtectedRoute редиректит без token, NotesList рендерит mock data, login 401 показывает ошибку. vi.mock() для модулей.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        ≥ 8 component tests. vitest run в CI. Тестирование internal state вместо visible behavior — хрупкие тесты. Cleanup mocks в afterEach — иначе тесты влияют друг на друга.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель React Testing Library — «тестируй как пользователь, а не как разработчик»: пользователь не знает про internal state или имена CSS-классов, он видит кнопки, лейблы и текст на экране. Поэтому getByRole и getByLabelText устойчивее к рефакторингу компонента, чем getByClassName или проверка state напрямую. Для junior frontend-позиции это стандарт индустрии — большинство современных React-команд требуют RTL-подход в тестах.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: если ты тестируешь wrapper.state.isLoggedIn === true вместо того, что видно на экране («Welcome» текст появился), рефакторинг компонента с useState на useReducer сломает тест, хотя поведение для пользователя не изменилось — это и есть хрупкий тест. Частое заблуждение — «чем больше моков, тем лучше изолирован тест» — избыточный mocking скрывает реальные баги интеграции; мокай только внешние границы (fetch, роутер), а не внутреннюю логику компонента. Компонентные тесты Login/ProtectedRoute/NotesList, которые ты пишешь сегодня, — прямой шаблон для тестов TaskList и NoteEditor в DevHub capstone (неделя 22, день 153), где потребуется уже ≥12 таких тестов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена связка Vitest + RTL особенно ценна на команде из нескольких frontend-разработчиков: когда кто-то меняет структуру JSX компонента ради рефакторинга, тесты, написанные через getByRole, продолжают проходить, а тесты через querySelector('.btn-submit') ломаются от простого переименования CSS-класса — разница напрямую влияет на то, сколько времени команда тратит на «починку зелёных тестов» после каждого рефакторинга вместо реальной разработки функциональности. Именно поэтому RTL стала де-факто стандартом тестирования React-компонентов в индустрии, а не просто одной из многих альтернатив — это первое, что спросят про фронтенд-тестирование на техническом собеседовании junior-разработчика.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: RTL — «как пользователь видит»; mock fetch, не implementation details.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom @testing-library/user-event
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Тест: Login form — submit вызывает API с email/password
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Тест: Protected route redirect на /login без token
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Mock API: register success, login 401 показывает ошибку
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Тест NotesList — рендерит заметки из mock response
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. npm test / vitest run в package.json scripts
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] vitest run проходит\n- [ ] Тесты ищут по role/label, не по className\n- [ ] ≥ 8 unit/component тестов

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm install -D vitest @testing-library/react @testing-library/jest-dom jsdom @testing-library/user-event
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Тест: Login form — submit вызывает API с email/password
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Тест: Protected route redirect на /login без token
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m \"week 20 day 138: Vitest auth and notes components\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Тестирование state вместо behavior — хрупкие тесты
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Забытый mock cleanup — тесты влияют друг на друга
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 139 (Сб): Интеграция auth frontend + backend

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Secure Notes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Full-stack auth связывает JWT backend с React frontend. Token storage: localStorage прост, но уязвим к XSS; httpOnly cookie безопаснее, сложнее с CORS. Для учебного проекта localStorage + CSP + sanitize input — приемлемо; задокументируй trade-off в README.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        AuthContext: user, token, login, logout, isLoading. api.ts wrapper подставляет Authorization: Bearer и на 401 очищает token + redirect /login. React Router <ProtectedRoute> оборачивает private pages. Token не в URL query string — утечёт в logs и history.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Full flow: register → login → create note → logout → login → note visible. User A не видит notes User B — проверь вручную и тестами. Axios interceptors или fetch wrapper — один вход для всех API calls.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: думай о AuthContext как о единственном источнике правды про личность пользователя во всём React-дереве — компоненты не хранят свою копию token, а читают из контекста через useAuth(). Это устраняет рассинхронизацию состояния, когда один компонент думает, что пользователь залогинен, а другой — нет. Для реальной работы junior full-stack разработчика это один из первых архитектурных паттернов, который придётся освоить: почти любое SPA с авторизацией использует похожую структуру (Context/Redux/Zustand + protected routes).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример проблемы без единого api-wrapper: если каждый компонент делает свой fetch и сам добавляет заголовок, то при истечении токена придётся чинить логику логаута в десятке мест — а с interceptor это одна точка изменения. Частое заблуждение — «localStorage полностью безопасен для токенов» — на деле любой XSS на странице получает доступ к localStorage через localStorage.getItem, поэтому в проде банки и финтех используют httpOnly cookie; для учебного проекта localStorage допустим при условии осознанного trade-off, задокументированного в README. Этот же auth flow — Context, api wrapper, protected routes — ты соберёшь заново, но уже с нуля, в DevHub capstone (неделя 22, день 151), так что качество кода сегодня напрямую экономит время через две недели.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена полезно явно проговорить trade-off хранения токена в коде и в README: это показывает ревьюеру портфолио, что решение осознанное, а не «забыл подумать про безопасность». Многие junior-кандидаты либо вообще не упоминают эту тему, либо копируют случайный код без понимания — а один абзац в README о том, почему выбран localStorage и какие меры снижают риск (CSP, sanitize, короткий TTL), выделяет проект среди типовых учебных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: auth flow end-to-end — контракт между Context, api wrapper и protected routes.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. React (Vite + TS): Login/Register pages с валидацией форм
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. AuthContext + useAuth() hook
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. api.ts wrapper — подставляет Bearer token, обрабатывает 401
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Protected routes — redirect /login если не авторизован
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Logout очищает token и context, redirect на login
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Full flow manual test: register → login → create note → logout → login again
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Full flow: register → login → access protected → logout\n- [ ] 401 от API → redirect login\n- [ ] Token не в URL query string

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. React (Vite + TS): Login/Register pages с валидацией форм
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. AuthContext + useAuth() hook
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. api.ts wrapper — подставляет Bearer token, обрабатывает 401
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m \"week 20 day 139: React auth integration\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • XSS + localStorage token — кража token (mitigate: CSP, sanitize input)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Token без expiration check на клиенте — плохой UX при expired
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 140 (Вс): Ревью безопасности и CI

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Secure Notes

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        CI автоматизирует проверку качества на каждый push. GitHub Actions: matrix jobs для backend (pytest) и frontend (vitest run). Зелёный CI — сигнал, что main mergeable. Branch protection с require CI — best practice для команд (обзор).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        npm audit и pip audit сканируют known vulnerabilities в зависимостях. Critical без комментария или плана фикса — красный флаг для портфолио. Semgrep — static analysis (обзор). Sequence diagram auth flow в README объясняет архитектуру ревьюеру.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Финальный security review по OWASP чеклисту. Обнови .env.example для backend и frontend. Smoke test checklist в README. Тег week-20-done — Secure Notes готов как шаблон для недель 21–22.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: CI — это автоматический привратник качества, который проверяет код за тебя каждый раз, когда ты забываешь. Зелёный чек на GitHub — не формальность для галочки, а сигнал команде (или ревьюеру портфолио), что код прошёл минимальную планку: тесты, линтер, security-скан. Для junior-кандидата наличие рабочего CI pipeline в pet-проекте на GitHub — заметный плюс: рекрутеры и техлиды буквально открывают вкладку Actions, чтобы увидеть зелёную галочку до того, как откроют код.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример пользы: npm audit может найти критическую уязвимость в транзитивной зависимости, о существовании которой ты даже не знал — типичный кейс cascading vulnerability в node_modules. Частое заблуждение — «раз мой код написан безопасно, зависимости не важны» — но большая часть реальных production-инцидентов происходит именно через уязвимые библиотеки третьих сторон, а не собственный код. Workflow ci.yml, который ты пишешь сегодня, — это шаблон, который в неделе 21 расширится healthcheck-ами для Docker, а в неделе 22 (день 153) вырастет до полноценного pipeline с postgres service и двумя параллельными job — тег week-20-done фиксирует рабочую точку отсчёта для этого пути.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена архитектурные решения без документации быстро забываются: через месяц ты сам не вспомнишь, почему выбран именно такой TTL токена или почему rate limit настроен на 5, а не на 10 попыток. Sequence diagram auth flow в README — не украшение, а инструмент передачи знаний будущему тебе или коллеге, который придёт поддерживать проект и не должен реверс-инжинирить логику по коду построчно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: CI + security audit — часть Definition of Done, не «после деплоя».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. .github/workflows/ci.yml: pytest + vitest run на push
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. npm audit и pip audit — отчёт в security-audit.md
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Документируй auth flow: sequence diagram в README
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Финальный security review по OWASP чеклисту
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Обнови .env.example для backend и frontend
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Smoke test checklist в README
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] CI workflow файл в .github/workflows/\n- [ ] npm audit — нет critical без комментария\n- [ ] Auth flow задокументирован

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. .github/workflows/ci.yml: pytest + vitest run на push
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. npm audit и pip audit — отчёт в security-audit.md
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Документируй auth flow: sequence diagram в README
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-20/git commit -m \"week 20 day 140: CI workflow and security docs\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поставь тег: git tag week-20-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Secure Notes API + React Client. Спецификация: docs/projects.md — неделя 20.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Стек

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Backend: Express или FastAPI — register, login, JWT, CRUD notes per user
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Security: bcrypt/passlib, rate limit на login, helmet/CORS
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Frontend: React + TypeScript — auth pages, protected dashboard, notes CRUD
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Tests: pytest ≥ 10, Vitest ≥ 8
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • CI: GitHub Actions green on push
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Регистрация и логин с JWT access token
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Notes привязаны к user_id из token
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. User A не может читать/менять notes User B → 403
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. React: AuthContext, protected routes, API wrapper
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. security-audit.md с OWASP чеклистом
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Пароли hashed, JWT в Authorization: Bearer header
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Rate limiting на /auth/login
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Frontend + backend тесты в CI
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • OWASP чеклист пройден и задокументирован
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Full auth flow работает end-to-end в браузере
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • README: env vars, run backend, run frontend, run tests
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Тег week-20-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • JWT vs session cookie — плюсы и минусы?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Как защититься от SQL injection и XSS?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Зачем rate limiting на login?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что тестирует React Testing Library?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что делать если JWT secret утёк в git?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Secure Notes** в `learning-log/week-20/`, осмысленная Git-история, тег `week-20-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nJWT auth, безопасность, тесты\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-20-day-134", "label": "День 134 (Пн): Аутентификация и хеширование паролей"}, {"id": "week-20-day-135", "label": "День 135 (Вт): JWT — выдача и проверка токенов"}, {"id": "week-20-day-136", "label": "День 136 (Ср): OWASP Top 10 — практическая защита"}, {"id": "week-20-day-137", "label": "День 137 (Чт): Тестирование backend — pytest"}, {"id": "week-20-day-138", "label": "День 138 (Пт): Тестирование frontend — Vitest"}, {"id": "week-20-day-139", "label": "День 139 (Сб): Интеграция auth frontend + backend"}, {"id": "week-20-day-140", "label": "День 140 (Вс): Ревью безопасности и CI"}, {"id": "week-20-project", "label": "Проект недели"}, {"id": "week-20-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-20-review", "label": "Проверь себя"}], "text": "Неделя 20: Auth, безопасность, тестирование Цель недели: реализовать JWT-аутентификацию, изучить OWASP и написать базовые тесты (Vitest + pytest). Литература: JWT.io , OWASP Top 10 , Vitest , pytest Проект недели: Secure Notes — JWT auth, bcrypt, rate limit, React client, pytest + Vitest. Git: папка learning-log/week-20/ , отдельные коммиты backend/frontend; тег week-20-done . День 134 (Пн): Аутентификация и хеширование паролей Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Secure Notes Теория Authentication отвечает на вопрос «кто ты?» — проверка личности (логин/пароль). Authorization — «что тебе можно?» — права на ресурсы. Не путай: успешный login не означает доступ ко всем endpoints. П…"} \ No newline at end of file diff --git a/docs/weeks/21.json b/docs/weeks/21.json index 9622589..7c08fc5 100644 --- a/docs/weeks/21.json +++ b/docs/weeks/21.json @@ -1 +1 @@ -{"id": "week-21", "title": "Docker", "fullTitle": "Неделя 21: Full-Stack интеграция и Docker", "html": "

                                                                                                                                                                                                                        Неделя 21: Full-Stack интеграция и Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: связать React-фронтенд с бэкендом и упаковать всё в Docker Compose.\nЛитература: Docker Docs, docker-compose, Vite Env\nПроект недели: Task Manager Docker — React + API + PostgreSQL в docker-compose, healthchecks, seed.\nGit: папка learning-log/week-21/, monorepo или два репо в одной папке; тег week-21-done.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 141 (Пн): Связка Frontend + Backend

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Full-stack начинается там, где фронтенд и бэкенд встречаются в браузере. Same-origin policy: localhost:5173 (Vite) и localhost:3000 (API) — разные origins. Браузер блокирует cross-origin fetch без заголовков CORS от сервера. Preflight OPTIONS запрос отправляется для «непростых» запросов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        cors middleware в Express или CORSMiddleware в FastAPI с whitelist http://localhost:5173. VITE_API_URL — build-time переменная для фронтенда; DATABASE_URL — runtime для бэкенда. Vite proxy в dev обходит CORS, направляя /api на backend — same-origin для браузера.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Замени localStorage tasks/notes на API CRUD — это суть недели. Проверь Network tab: нет CORS errors. .env.example для обоих проектов. Hardcoded localhost в production build — сломает deploy.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: CORS — согласие сервера; VITE_ prefix обязателен для клиентских env.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. React Dashboard (нед.14) или Secure Notes (нед.20) → fetch к Express/FastAPI API
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. .env: VITE_API_URL=http://localhost:3000 (или 8000 для FastAPI)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CORS: allow http://localhost:5173 в dev, credentials если нужны cookies
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Замени localStorage tasks/notes на API CRUD
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь Network tab — нет CORS errors
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. .env.example для обоих проектов
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] CRUD через API, не localStorage\n- [ ] CORS настроен — нет ошибки в browser console\n- [ ] .env.example для обоих проектов

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. React Dashboard (нед.14) или Secure Notes (нед.20) → fetch к Express/FastAPI API
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. .env: VITE_API_URL=http://localhost:3000 (или 8000 для FastAPI)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CORS: allow http://localhost:5173 в dev, credentials если нужны cookies
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-21/git commit -m \"week 21 day 141: frontend backend CORS integration\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • VITE_ prefix обязателен — иначе переменная не попадёт в bundle
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Hardcoded localhost в production build
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 142 (Вт): Единый API-контракт и обработка ошибок

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        API contract — общий язык фронтенда и бэкенда. OpenAPI/Swagger — source of truth: типы, статусы, примеры. Единый формат ошибок { error: { code, message, details? } } упрощает парсинг на клиенте. 4xx — «ты сделал что-то не так», 5xx — «попробуй позже».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Три UI-состояния на каждой data-fetching странице: loading (spinner), error (message + retry), empty (подсказка действия). services/api.ts — единый fetch wrapper с auth header и error parsing; не дублируй fetch в 10 компонентах. TypeScript types Task, ApiError в types/api.ts.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверяй res.ok перед json() — иначе парсишь HTML error page как JSON. React Query/SWR — опционально для кеша и retry. Сверь frontend types с OpenAPI вручную или через openapi-typescript.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: один api module; loading/error/empty — не опциональный UX.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. services/api.ts — единый fetch wrapper с error parsing и auth header
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Все страницы: loading spinner, error message + retry button, empty state
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Toast при успешном create/update/delete (или inline feedback)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Типы Task, Note, ApiError в types/api.ts
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. 4xx показывает user-friendly message; 5xx — «Попробуйте позже»
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сверь frontend types с OpenAPI schema (ручно или openapi-typescript)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Один api module, не fetch в каждом компоненте\n- [ ] Network error показывает понятное сообщение\n- [ ] 4xx/5xx обрабатываются по-разному

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. services/api.ts — единый fetch wrapper с error parsing и auth header
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Все страницы: loading spinner, error message + retry button, empty state
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Toast при успешном create/update/delete (или inline feedback)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-21/git commit -m \"week 21 day 142: API client loading error states\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Дублирование fetch логики в 10 компонентах
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Игнорирование res.ok — парсинг error HTML как JSON
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 143 (Ср): Docker — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Docker упаковывает приложение с зависимостями в воспроизводимый образ. Image — неизменяемый шаблон (слои); container — запущенный экземпляр. Dockerfile: FROM node:20-alpine, WORKDIR, COPY package*.json, RUN npm ci, COPY ., EXPOSE, CMD. Layer caching: сначала зависимости, потом код — быстрее rebuild.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        .dockerignore исключает node_modules, .git, .env из build context. docker build -t task-api . и docker run -p 3000:3000 --env-file .env task-api. Multi-stage builds (обзор): build stage + slim runtime. curl localhost:3000/api/health с хоста проверяет container.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не копируй весь проект до npm ci — инвалидируешь cache. Root user в container — для prod consider non-root (обзор). Документируй docker commands в README.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: image = шаблон, container = процесс; слои Dockerfile — про скорость сборки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Dockerfile для backend: node:20-alpine или python:3.12-slim
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. COPY package files → install deps → COPY source → EXPOSE port → CMD
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. docker build -t task-api . и docker run -p 3000:3000 --env-file .env task-api
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь /health с хоста: curl localhost:3000/api/health
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. .dockerignore: node_modules, .git, .env, pycache
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Задокументируй команды в README
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Image собирается без ошибок\n- [ ] .dockerignore исключает node_modules\n- [ ] Container стартует и отвечает на /health

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Dockerfile для backend: node:20-alpine или python:3.12-slim
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. COPY package files → install deps → COPY source → EXPOSE port → CMD
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. docker build -t task-api . и docker run -p 3000:3000 --env-file .env task-api
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-21/git commit -m \"week 21 day 143: backend Dockerfile\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • COPY всего проекта до npm ci — layer cache invalidation
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • root user в container — для prod consider non-root (обзор)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 144 (Чт): Docker для frontend и PostgreSQL

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Production frontend в Docker — multi-stage: stage 1 npm run build (Node), stage 2 nginx:alpine копирует dist/. nginx отдаёт static assets с gzip; try_files $uri /index.html — SPA fallback для client-side routes. VITE_API_URL — build-time: пересобирай image при смене API URL.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Official postgres:16 image: env POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB. Named volume pgdata:/var/lib/postgresql/data — данные переживают docker rm. localhost внутри container — сам container, не host machine; в compose network используй имя service db.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подними три container вручную перед compose: frontend :80, API :3000, PG :5432. Backend подключается к postgres по hostname db в docker network. Проверь полный flow до docker compose.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: в docker network хост БД — имя service, не localhost.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Frontend Dockerfile: stage 1 npm run build, stage 2 nginx:alpine + COPY dist
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. docker run -d --name pg -e POSTGRES_PASSWORD=pass -v pgdata:/var/lib/postgresql/data postgres:16
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Backend container подключается к postgres по hostname (вручную: --link или host.docker.internal)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. nginx.conf: try_files $uri /index.html для SPA routing
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь полный flow: 3 containers вручную
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Frontend на port 80, API на 3000, PG на 5432
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Frontend dist отдаётся nginx на port 80\n- [ ] Postgres data сохраняется после restart container\n- [ ] Backend видит DB по hostname db (в compose network)

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Frontend Dockerfile: stage 1 npm run build, stage 2 nginx:alpine + COPY dist
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. docker run -d --name pg -e POSTGRES_PASSWORD=pass -v pgdata:/var/lib/postgresql/data postgres:16
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Backend container подключается к postgres по hostname (вручную: --link или host.docker.internal)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-21/git commit -m \"week 21 day 144: frontend nginx and postgres containers\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • localhost внутри container — это сам container, не host
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • VITE_API_URL при build time — пересобирай image при смене URL
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 145 (Пт): docker-compose — multi-service

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        docker-compose оркестрирует multi-service приложение одним файлом. Services: db, backend, frontend; networks связывают их; volumes persist data. depends_on задаёт порядок старта, но не готовность БД — добавь healthcheck pg_isready и condition: service_healthy.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DATABASE_URL=postgresql://user:pass@db:5432/tasks — hostname db из имени service. docker compose up --build — одна команда для всего стека. docker compose down -v удаляет volumes — осторожно, потеряешь данные. Seed в entrypoint или init service.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Smoke test: open frontend → login → create task → refresh → persists. Healthchecks на db и /api/health на backend — обязательны для надёжного старта. Эта структура monorepo — прямой задел для DevHub capstone.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: compose + healthcheck + volumes = воспроизводимый full-stack локально.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. docker-compose.yml:
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. DATABASE_URL=postgresql://user:pass@db:5432/tasks в backend env
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. docker compose up --build — всё стартует одной командой
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Seed script в backend entrypoint или отдельный init service
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь smoke: open frontend → login → create task\n - db (postgres:16 + volume pgdata + healthcheck)\n - backend (build ./backend, ports 3000, depends_on db healthy)\n - frontend (build ./frontend, ports 8080:80)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Одна команда поднимает 3 сервиса\n- [ ] Данные PG в named volume pgdata\n- [ ] depends_on + healthcheck db

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. docker-compose.yml:
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. DATABASE_URL=postgresql://user:pass@db:5432/tasks в backend env
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. docker compose up --build — всё стартует одной командой
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-21/git commit -m \"week 21 day 145: docker-compose three services\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Backend стартует до готовности PG — connection refused (healthcheck/retry)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • docker compose down -v — удаляет данные (осторожно)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 146 (Сб): Dev vs Prod конфигурация

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        12 Factor App: config в environment, dev/prod parity, disposability (containers стартуют быстро). docker-compose.override.yml автоматически мержится в dev; docker-compose.prod.yml — explicit -f для production-like local. Dev: volume mount source + nodemon/uvicorn --reload; prod: optimized image без mounts.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Логи: docker compose logs -f backend. Secrets в prod — Docker secrets или cloud env, не plain text в compose file. Entrypoint script: wait-for-db → migrate → seed → start server — решает race condition при старте.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Документируй порты и команды: dev docker compose up vs prod docker compose -f docker-compose.prod.yml up. Dev volume mount может перезаписать node_modules в container — используй named volume для node_modules (обзор). Default passwords только для local.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: dev/prod compose — разные файлы, одна документация в README.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. docker-compose.dev.yml — mount source, hot reload, exposed debug ports
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. docker-compose.prod.yml — optimized builds, no volume mounts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. README: docker compose up (dev) vs docker compose -f docker-compose.prod.yml up
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Entrypoint script: wait-for-db → migrate → seed → start server
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. .env.example со всеми переменными для compose
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Документируй порты: frontend 8080, api 3000, db 5432
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Dev и prod compose файлы документированы\n- [ ] Seed data появляется после первого up\n- [ ] Логи доступны через compose logs

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. docker-compose.dev.yml — mount source, hot reload, exposed debug ports
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. docker-compose.prod.yml — optimized builds, no volume mounts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. README: docker compose up (dev) vs docker compose -f docker-compose.prod.yml up
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-21/git commit -m \"week 21 day 146: dev prod compose configs\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Dev volume mount перезаписывает node_modules в container
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Production compose с default passwords — только для local
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 147 (Вс): E2E smoke test и ревью архитектуры

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Smoke test — минимальный путь пользователя, не полный E2E suite. SMOKE_TEST.md: compose up → open app → login → CRUD task → refresh → data persists. Health endpoints нужны orchestration (Kubernetes, Render, compose healthcheck). Architecture diagram (Mermaid): client → API → DB → volumes.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Замерь cold start docker compose up --build — free tier deploy может иметь 30–60 сек warm-up; документируй в README. Сравни week-21 с требованиями DevHub capstone — список gaps в notes/capstone-prep.md. Все env vars в .env.example.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Неделя 21 — мост к финалу: та же структура frontend/ + backend/ + docker-compose.yml. Тег week-21-done. Если smoke test проходит — ты готов к DevHub.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: smoke test + architecture diagram — входной билет в capstone неделю.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Smoke checklist в SMOKE_TEST.md: compose up → open app → login → CRUD task → refresh → persists
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Mermaid diagram в README: frontend, backend, db, volumes
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Замер cold start docker compose up --build — запиши время
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь все env vars в .env.example
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Сравни week-21 с требованиями DevHub Capstone — что уже готово
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Список gaps для capstone в notes/capstone-prep.md
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Smoke test checklist пройден\n- [ ] Mermaid diagram в README\n- [ ] Все env vars в .env.example

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Smoke checklist в SMOKE_TEST.md: compose up → open app → login → CRUD task → refresh → persists
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Mermaid diagram в README: frontend, backend, db, volumes
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Замер cold start docker compose up --build — запиши время
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-21/git commit -m \"week 21 day 147: smoke test and architecture diagram\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поставь тег: git tag week-21-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Full-Stack Task Manager в Docker. Спецификация: docs/projects.md — неделя 21.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура monorepo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        week-21/\n├── frontend/           # Vite React TS\n├── backend/            # Express or FastAPI\n├── docker-compose.yml\n├── docker-compose.dev.yml\n├── .env.example\n├── SMOKE_TEST.md\n└── README.md\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. React frontend + Express/FastAPI backend + PostgreSQL
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Auth (JWT из нед. 20), tasks CRUD через API
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. docker-compose.yml — db, backend, frontend
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Volumes, healthchecks, seed data, wait-for-db
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Dev и prod инструкции, architecture diagram
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • docker compose up --build — working app на localhost
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Данные переживают restart (named volume)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • CORS и VITE_API_URL корректны для docker network
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Healthcheck на db и /api/health на backend
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • SMOKE_TEST.md пройден без ошибок
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • README: architecture, env, dev vs prod commands
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Тег week-21-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Этот проект — прямой задел для DevHub Capstone: та же структура frontend/ + backend/ + docker-compose.yml.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Зачем Docker если можно npm start локально?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Чем image отличается от container?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Почему localhost внутри container не работает для host DB?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что такое CORS и когда браузер блокирует запрос?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • docker-compose vs kubernetes — когда что (обзор)?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Task Manager Docker** в `learning-log/week-21/`, осмысленная Git-история, тег `week-21-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nFull-stack в Docker Compose\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-21-day-141", "label": "День 141 (Пн): Связка Frontend + Backend"}, {"id": "week-21-day-142", "label": "День 142 (Вт): Единый API-контракт и обработка ошибок"}, {"id": "week-21-day-143", "label": "День 143 (Ср): Docker — основы"}, {"id": "week-21-day-144", "label": "День 144 (Чт): Docker для frontend и PostgreSQL"}, {"id": "week-21-day-145", "label": "День 145 (Пт): docker-compose — multi-service"}, {"id": "week-21-day-146", "label": "День 146 (Сб): Dev vs Prod конфигурация"}, {"id": "week-21-day-147", "label": "День 147 (Вс): E2E smoke test и ревью архитектуры"}, {"id": "week-21-project", "label": "Проект недели"}, {"id": "week-21-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-21-review", "label": "Проверь себя"}], "text": "Неделя 21: Full-Stack интеграция и Docker Цель недели: связать React-фронтенд с бэкендом и упаковать всё в Docker Compose. Литература: Docker Docs , docker-compose , Vite Env Проект недели: Task Manager Docker — React + API + PostgreSQL в docker-compose , healthchecks, seed. Git: папка learning-log/week-21/ , monorepo или два репо в одной папке; тег week-21-done . День 141 (Пн): Связка Frontend + Backend Время (полный): ~55м теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~25м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Task Manager Docker Теория Full-stack начинается там, где фронтенд и бэкенд встречаются в браузере. Same-origin policy: localhost:5173 (Vite) и localhost:3000 (API) — разные origins. Браузер блокирует cross-origin fetch без заголовков CORS о…"} \ No newline at end of file +{"id": "week-21", "title": "Docker", "fullTitle": "Неделя 21: Full-Stack интеграция и Docker", "html": "

                                                                                                                                                                                                                        Неделя 21: Full-Stack интеграция и Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: связать React-фронтенд с бэкендом и упаковать всё в Docker Compose.\nЛитература: Docker Docs, docker-compose, Vite Env\nПроект недели: Task Manager Docker — React + API + PostgreSQL в docker-compose, healthchecks, seed.\nGit: папка learning-log/week-21/, monorepo или два репо в одной папке; тег week-21-done.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 141 (Пн): Связка Frontend + Backend

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Full-stack начинается там, где фронтенд и бэкенд встречаются в браузере. Same-origin policy: localhost:5173 (Vite) и localhost:3000 (API) — разные origins. Браузер блокирует cross-origin fetch без заголовков CORS от сервера. Preflight OPTIONS запрос отправляется для «непростых» запросов.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        cors middleware в Express или CORSMiddleware в FastAPI с whitelist http://localhost:5173. VITE_API_URL — build-time переменная для фронтенда; DATABASE_URL — runtime для бэкенда. Vite proxy в dev обходит CORS, направляя /api на backend — same-origin для браузера.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Замени localStorage tasks/notes на API CRUD — это суть недели. Проверь Network tab: нет CORS errors. .env.example для обоих проектов. Hardcoded localhost в production build — сломает deploy.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: origin — это тройка (протокол, домен, порт), и браузер по умолчанию блокирует любой fetch между разными origin, если сервер явно не разрешил это через CORS-заголовки. Это защита пользователя, а не бага фреймворка — без same-origin policy любой сайт мог бы читать твою банковскую сессию через скрытый fetch. Для junior full-stack разработчика непонимание CORS — источник часа-двух бесполезной отладки почти в каждом первом проекте; умение быстро прочитать ошибку CORS в консоли и понять, на чьей она стороне (сервер не разрешил origin) — практический навык уровня middle.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: если VITE_API_URL не имеет префикса VITE_, Vite просто не включит переменную в bundle — переменная будет undefined в runtime, и ошибка проявится не как CORS, а как fetch на undefined/api/tasks, что сбивает с толку новичков. Частое заблуждение — «CORS настраивается на клиенте» — на самом деле разрешение полностью на стороне сервера (заголовки Access-Control-Allow-Origin), клиент только соблюдает то, что разрешил браузер. Именно этот CORS-контракт между React-клиентом и API — фундамент для docker-compose сети в этой же неделе (день 145), где origin меняются на container hostnames, и для production deploy в DevHub capstone, где появится третий origin — Vercel domain.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена preflight OPTIONS-запрос — источник ещё одной частой путаницы: браузер отправляет его автоматически перед «непростыми» запросами (с кастомными заголовками вроде Authorization или методом PUT/DELETE), и сервер должен явно ответить на OPTIONS без падения — иначе основной запрос до сервера вообще не дойдёт, а в Network tab будет видна только неудачная preflight-строка, что сбивает с толку при первой отладке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: CORS — согласие сервера; VITE_ prefix обязателен для клиентских env.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. React Dashboard (нед.14) или Secure Notes (нед.20) → fetch к Express/FastAPI API
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. .env: VITE_API_URL=http://localhost:3000 (или 8000 для FastAPI)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CORS: allow http://localhost:5173 в dev, credentials если нужны cookies
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Замени localStorage tasks/notes на API CRUD
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь Network tab — нет CORS errors
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. .env.example для обоих проектов
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] CRUD через API, не localStorage\n- [ ] CORS настроен — нет ошибки в browser console\n- [ ] .env.example для обоих проектов

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. React Dashboard (нед.14) или Secure Notes (нед.20) → fetch к Express/FastAPI API
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. .env: VITE_API_URL=http://localhost:3000 (или 8000 для FastAPI)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CORS: allow http://localhost:5173 в dev, credentials если нужны cookies
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-21/git commit -m \"week 21 day 141: frontend backend CORS integration\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • VITE_ prefix обязателен — иначе переменная не попадёт в bundle
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Hardcoded localhost в production build
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 142 (Вт): Единый API-контракт и обработка ошибок

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        API contract — общий язык фронтенда и бэкенда. OpenAPI/Swagger — source of truth: типы, статусы, примеры. Единый формат ошибок { error: { code, message, details? } } упрощает парсинг на клиенте. 4xx — «ты сделал что-то не так», 5xx — «попробуй позже».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Три UI-состояния на каждой data-fetching странице: loading (spinner), error (message + retry), empty (подсказка действия). services/api.ts — единый fetch wrapper с auth header и error parsing; не дублируй fetch в 10 компонентах. TypeScript types Task, ApiError в types/api.ts.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверяй res.ok перед json() — иначе парсишь HTML error page как JSON. React Query/SWR — опционально для кеша и retry. Сверь frontend types с OpenAPI вручную или через openapi-typescript.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: API contract — это письменный договор между командами (или между тобой сегодняшним и тобой через месяц), а не подразумеваемое соглашение в голове. Если backend меняет форму ошибки без предупреждения, frontend ломается тихо — вот почему OpenAPI-схема и типизированные ошибки экономят часы интеграционной отладки. В реальных компаниях frontend и backend часто пишут разные люди или разные команды, и контракт — единственное, что синхронизирует их работу без созвонов на каждый чих.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: если API возвращает { error: \"Not found\" } в одном endpoint и { message: \"Not found\", code: 404 } в другом, frontend не может написать один универсальный error handler — придётся городить if-ветки под каждый случай, что быстро превращается в технический долг. Частое заблуждение junior-разработчиков — «раз fetch не выбросил exception, значит всё ок» — но fetch не бросает ошибку на HTTP 404/500, только на сетевой сбой, поэтому проверка res.ok обязательна перед res.json(), иначе распарсишь HTML-страницу ошибки как JSON и получишь непонятный краш. Три состояния — loading/error/empty, которые ты добавляешь сегодня на каждую страницу, станут обязательным критерием приёмки для Dashboard и Tasks в DevHub capstone (неделя 22, день 150) — привычка, заложенная сейчас, там уже не потребует отдельного обдумывания.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена единый services/api.ts даёт ещё один практический бонус — единую точку для будущих улучшений вроде retry с exponential backoff или отмены запроса при размонтировании компонента (AbortController). Если fetch-логика раскидана по компонентам, добавление такой функциональности требует правки в десятке мест и почти гарантированно приводит к рассинхронизации поведения между страницами.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: один api module; loading/error/empty — не опциональный UX.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. services/api.ts — единый fetch wrapper с error parsing и auth header
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Все страницы: loading spinner, error message + retry button, empty state
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Toast при успешном create/update/delete (или inline feedback)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Типы Task, Note, ApiError в types/api.ts
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. 4xx показывает user-friendly message; 5xx — «Попробуйте позже»
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Сверь frontend types с OpenAPI schema (ручно или openapi-typescript)
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Один api module, не fetch в каждом компоненте\n- [ ] Network error показывает понятное сообщение\n- [ ] 4xx/5xx обрабатываются по-разному

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. services/api.ts — единый fetch wrapper с error parsing и auth header
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Все страницы: loading spinner, error message + retry button, empty state
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Toast при успешном create/update/delete (или inline feedback)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-21/git commit -m \"week 21 day 142: API client loading error states\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Дублирование fetch логики в 10 компонентах
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Игнорирование res.ok — парсинг error HTML как JSON
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 143 (Ср): Docker — основы

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Docker упаковывает приложение с зависимостями в воспроизводимый образ. Image — неизменяемый шаблон (слои); container — запущенный экземпляр. Dockerfile: FROM node:20-alpine, WORKDIR, COPY package*.json, RUN npm ci, COPY ., EXPOSE, CMD. Layer caching: сначала зависимости, потом код — быстрее rebuild.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        .dockerignore исключает node_modules, .git, .env из build context. docker build -t task-api . и docker run -p 3000:3000 --env-file .env task-api. Multi-stage builds (обзор): build stage + slim runtime. curl localhost:3000/api/health с хоста проверяет container.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не копируй весь проект до npm ci — инвалидируешь cache. Root user в container — для prod consider non-root (обзор). Документируй docker commands в README.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: Dockerfile — рецепт, image — испечённый и замороженный пирог по рецепту, container — кусок этого пирога у тебя на тарелке прямо сейчас, который можно есть (запускать), выбросить и отрезать заново. Слои Dockerfile кешируются построчно сверху вниз, поэтому порядок инструкций — это оптимизация скорости сборки, а не просто стиль. Для junior-разработчика Docker — это уже не «плюс», а базовое требование в большинстве вакансий 2026 года: почти любая современная инфраструктура (Kubernetes, ECS, Render, Railway) ожидает готовый Docker image.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример цены ошибки: если скопировать весь проект (COPY . .) до npm ci, то любое изменение в исходном коде инвалидирует кеш зависимостей — пересборка занимает минуты вместо секунд при каждом маленьком изменении кода. Частое заблуждение новичков — «Docker — это как виртуальная машина» — на деле контейнеры используют namespaces и cgroups ядра хоста, а не эмулируют железо, поэтому стартуют за миллисекунды, а не минуты, и делят ядро ОС с хостом. Dockerfile для backend, который ты пишешь сегодня, станет первым сервисом в docker-compose.yml (день 145), а затем — основой Docker-инфраструктуры DevHub capstone (неделя 22, день 152), где та же логика слоёв применится уже к production-сборке.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена размер образа тоже имеет значение: node:20-alpine весит десятки мегабайт против сотен у полного node:20, а меньший образ быстрее скачивается при деплое и содержит меньше поверхности для атак (меньше системных пакетов — меньше потенциальных CVE). Привычка сразу выбирать slim/alpine базовые образы, а не «full», экономит время и деньги на облачном биллинге по трафику и storage в масштабе реальной инфраструктуры.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: image = шаблон, container = процесс; слои Dockerfile — про скорость сборки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Dockerfile для backend: node:20-alpine или python:3.12-slim
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. COPY package files → install deps → COPY source → EXPOSE port → CMD
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. docker build -t task-api . и docker run -p 3000:3000 --env-file .env task-api
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь /health с хоста: curl localhost:3000/api/health
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. .dockerignore: node_modules, .git, .env, pycache
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Задокументируй команды в README
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Image собирается без ошибок\n- [ ] .dockerignore исключает node_modules\n- [ ] Container стартует и отвечает на /health

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Dockerfile для backend: node:20-alpine или python:3.12-slim
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. COPY package files → install deps → COPY source → EXPOSE port → CMD
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. docker build -t task-api . и docker run -p 3000:3000 --env-file .env task-api
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-21/git commit -m \"week 21 day 143: backend Dockerfile\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • COPY всего проекта до npm ci — layer cache invalidation
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • root user в container — для prod consider non-root (обзор)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 144 (Чт): Docker для frontend и PostgreSQL

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Production frontend в Docker — multi-stage: stage 1 npm run build (Node), stage 2 nginx:alpine копирует dist/. nginx отдаёт static assets с gzip; try_files $uri /index.html — SPA fallback для client-side routes. VITE_API_URL — build-time: пересобирай image при смене API URL.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Official postgres:16 image: env POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB. Named volume pgdata:/var/lib/postgresql/data — данные переживают docker rm. localhost внутри container — сам container, не host machine; в compose network используй имя service db.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Подними три container вручную перед compose: frontend :80, API :3000, PG :5432. Backend подключается к postgres по hostname db в docker network. Проверь полный flow до docker compose.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: named volume — это внешний жёсткий диск, который ты подключаешь к контейнеру; сам контейнер — расходный, а volume переживает docker rm и пересоздание контейнера. Путаница «localhost внутри контейнера = localhost на хосте» — одна из самых частых ошибок новичков в Docker: у каждого контейнера своя сетевая изоляция, и «localhost» там означает сам контейнер, а не машину разработчика. В production-командах эта путаница стоит часов отладки connection refused, поэтому понимание docker network — маркер зрелости junior DevOps-навыков.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: если backend в контейнере пытается подключиться к Postgres по localhost:5432, он получит connection refused, даже если Postgres реально запущен и слушает порт — потому что это два разных сетевых namespace; правильный hostname — имя service (db) в общей docker-сети. Частое заблуждение — «раз я указал -p 5432:5432, значит порт открыт для всех контейнеров» — port mapping открывает порт наружу на хост-машину, а между контейнерами используется внутренняя docker network с DNS по именам сервисов. Multi-stage сборка frontend (build + nginx), которую ты делаешь сегодня, и правильное именование сервисов — прямая подготовка к docker-compose.yml завтрашнего дня и к продовому образу DevHub capstone.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена nginx как раздатчик статики — не случайный выбор: он эффективнее Node.js-сервера для отдачи файлов благодаря event-driven архитектуре, умеет gzip/brotli-сжатие «из коробки» и не тратит ресурсы на интерпретацию JavaScript ради банальной раздачи HTML/CSS/JS. try_files $uri /index.html решает специфичную для SPA проблему: без этой директивы прямой заход на /tasks (не через клик в приложении) вернёт 404, потому что физического файла /tasks на диске не существует — весь роутинг живёт в JS-бандле.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: в docker network хост БД — имя service, не localhost.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Frontend Dockerfile: stage 1 npm run build, stage 2 nginx:alpine + COPY dist
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. docker run -d --name pg -e POSTGRES_PASSWORD=pass -v pgdata:/var/lib/postgresql/data postgres:16
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Backend container подключается к postgres по hostname (вручную: --link или host.docker.internal)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. nginx.conf: try_files $uri /index.html для SPA routing
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь полный flow: 3 containers вручную
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Frontend на port 80, API на 3000, PG на 5432
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Frontend dist отдаётся nginx на port 80\n- [ ] Postgres data сохраняется после restart container\n- [ ] Backend видит DB по hostname db (в compose network)

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Frontend Dockerfile: stage 1 npm run build, stage 2 nginx:alpine + COPY dist
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. docker run -d --name pg -e POSTGRES_PASSWORD=pass -v pgdata:/var/lib/postgresql/data postgres:16
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Backend container подключается к postgres по hostname (вручную: --link или host.docker.internal)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Документация не клеится — найди один официальный пример (MDN / docs) и сопоставь 1:1 со своим кодом.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-21/git commit -m \"week 21 day 144: frontend nginx and postgres containers\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • localhost внутри container — это сам container, не host
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • VITE_API_URL при build time — пересобирай image при смене URL
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 145 (Пт): docker-compose — multi-service

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        docker-compose оркестрирует multi-service приложение одним файлом. Services: db, backend, frontend; networks связывают их; volumes persist data. depends_on задаёт порядок старта, но не готовность БД — добавь healthcheck pg_isready и condition: service_healthy.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DATABASE_URL=postgresql://user:pass@db:5432/tasks — hostname db из имени service. docker compose up --build — одна команда для всего стека. docker compose down -v удаляет volumes — осторожно, потеряешь данные. Seed в entrypoint или init service.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Smoke test: open frontend → login → create task → refresh → persists. Healthchecks на db и /api/health на backend — обязательны для надёжного старта. Эта структура monorepo — прямой задел для DevHub capstone.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: docker-compose.yml — это партитура для оркестра из нескольких контейнеров, где каждый service — отдельный музыкант, а networks и volumes — то, что позволяет им играть вместе и не терять данные между выступлениями. depends_on говорит Docker только порядок запуска процессов, а не готовность приложения внутри — Postgres-контейнер стартует за миллисекунды, но самому PostgreSQL нужны секунды на инициализацию, поэтому без healthcheck backend может упасть с connection refused при первом старте.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: condition: service_healthy вместе с pg_isready в healthcheck заставляет Docker дождаться реальной готовности БД принимать соединения, а не просто факта, что контейнер запущен — это разница между «процесс существует» и «процесс готов работать», критичная для надёжного docker compose up без ручных перезапусков. Частое заблуждение — «docker compose down безопасен всегда» — но флаг -v удаляет volumes вместе с данными, и разработчики теряли демо-данные перед показом проекта именно так. Инфраструктура из трёх сервисов с healthcheck, которую ты собираешь сегодня, — это практически готовый docker-compose.yml для DevHub capstone (неделя 22, день 152), где добавится только auth layer и production-нюансы.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена важно понимать разницу между healthcheck и readiness: даже здоровый (healthy) контейнер может быть временно не готов принимать нагрузку (например, прогревает кеш) — в managed-оркестраторах вроде Kubernetes это два разных сигнала (liveness/readiness probes), но идея та же самая, что и в compose healthcheck: не отправляй трафик туда, где сервис формально жив, но фактически ещё не готов отвечать корректно. Эта идея пригодится и за пределами Docker — в любой системе с несколькими зависимыми сервисами.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: compose + healthcheck + volumes = воспроизводимый full-stack локально.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. docker-compose.yml:
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. DATABASE_URL=postgresql://user:pass@db:5432/tasks в backend env
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. docker compose up --build — всё стартует одной командой
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Seed script в backend entrypoint или отдельный init service
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь smoke: open frontend → login → create task\n - db (postgres:16 + volume pgdata + healthcheck)\n - backend (build ./backend, ports 3000, depends_on db healthy)\n - frontend (build ./frontend, ports 8080:80)
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Одна команда поднимает 3 сервиса\n- [ ] Данные PG в named volume pgdata\n- [ ] depends_on + healthcheck db

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. docker-compose.yml:
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. DATABASE_URL=postgresql://user:pass@db:5432/tasks в backend env
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. docker compose up --build — всё стартует одной командой
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-21/git commit -m \"week 21 day 145: docker-compose three services\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Backend стартует до готовности PG — connection refused (healthcheck/retry)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • docker compose down -v — удаляет данные (осторожно)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 146 (Сб): Dev vs Prod конфигурация

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        12 Factor App: config в environment, dev/prod parity, disposability (containers стартуют быстро). docker-compose.override.yml автоматически мержится в dev; docker-compose.prod.yml — explicit -f для production-like local. Dev: volume mount source + nodemon/uvicorn --reload; prod: optimized image без mounts.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Логи: docker compose logs -f backend. Secrets в prod — Docker secrets или cloud env, не plain text в compose file. Entrypoint script: wait-for-db → migrate → seed → start server — решает race condition при старте.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Документируй порты и команды: dev docker compose up vs prod docker compose -f docker-compose.prod.yml up. Dev volume mount может перезаписать node_modules в container — используй named volume для node_modules (обзор). Default passwords только для local.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель 12 Factor App: конфигурация должна жить в environment variables, а не в коде — тот же image должен уметь запускаться и в dev, и в staging, и в проде, отличаясь только переменными окружения снаружи. Dev/prod parity — принцип, по которому окружения должны быть максимально похожи, чтобы баг «работает у меня, не работает в проде» случался как можно реже. Для junior-разработчика эта дисциплина — то, что отличает pet-проект от продакшен-готового кода: собеседующие часто спрашивают именно про разделение dev/prod конфигурации.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример проблемы: volume mount исходников в dev-режиме (-v ./backend:/app) может незаметно перезаписать node_modules внутри контейнера локальной версией с хоста, если не выделить отдельный named volume под node_modules — итог: контейнер падает с «module not found», хотя на хосте всё установлено. Частое заблуждение — «дефолтные пароли postgres в compose-файле не проблема, это же локально» — но такие compose-файлы часто копируют в staging без изменений, и default password утекает в реальную инфраструктуру. Entrypoint-скрипт wait-for-db → migrate → seed, который ты пишешь сегодня, решает ту же race condition, что встретится в проде DevHub capstone при первом деплое (неделя 22, день 154) — паттерн одинаков в любом окружении.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена явное разделение dev/prod compose файлов вместо одного «универсального» с кучей if-подобных условий — это разница между конфигурацией, которую можно быстро прочитать и понять, и конфигурацией, требующей мысленно эмулировать все возможные комбинации флагов. Команды, где такое разделение принято с самого начала, тратят заметно меньше времени на «почему в проде включился dev-режим» — классический класс инцидентов из-за спутанной конфигурации.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: dev/prod compose — разные файлы, одна документация в README.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. docker-compose.dev.yml — mount source, hot reload, exposed debug ports
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. docker-compose.prod.yml — optimized builds, no volume mounts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. README: docker compose up (dev) vs docker compose -f docker-compose.prod.yml up
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Entrypoint script: wait-for-db → migrate → seed → start server
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. .env.example со всеми переменными для compose
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Документируй порты: frontend 8080, api 3000, db 5432
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Dev и prod compose файлы документированы\n- [ ] Seed data появляется после первого up\n- [ ] Логи доступны через compose logs

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. docker-compose.dev.yml — mount source, hot reload, exposed debug ports
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. docker-compose.prod.yml — optimized builds, no volume mounts
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. README: docker compose up (dev) vs docker compose -f docker-compose.prod.yml up
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-21/git commit -m \"week 21 day 146: dev prod compose configs\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Dev volume mount перезаписывает node_modules в container
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Production compose с default passwords — только для local
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 147 (Вс): E2E smoke test и ревью архитектуры

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к Task Manager Docker

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Smoke test — минимальный путь пользователя, не полный E2E suite. SMOKE_TEST.md: compose up → open app → login → CRUD task → refresh → data persists. Health endpoints нужны orchestration (Kubernetes, Render, compose healthcheck). Architecture diagram (Mermaid): client → API → DB → volumes.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Замерь cold start docker compose up --build — free tier deploy может иметь 30–60 сек warm-up; документируй в README. Сравни week-21 с требованиями DevHub capstone — список gaps в notes/capstone-prep.md. Все env vars в .env.example.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Неделя 21 — мост к финалу: та же структура frontend/ + backend/ + docker-compose.yml. Тег week-21-done. Если smoke test проходит — ты готов к DevHub.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: smoke test — это не полный regression suite, а быстрая проверка «дым идёт, значит мотор хотя бы завёлся» — минимальный путь, который ловит catastrophic failures за минуту вместо часа полного прогона тестов. Architecture diagram решает другую задачу — она переводит код в общий язык для ревьюера, коллеги или будущего тебя, который забыл детали через полгода. Для junior-разработчика умение за 2 минуты нарисовать архитектуру своего проекта на созвоне — практический навык, который прямо оценивают на техническом интервью.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: если docker compose up --build первый раз занимает 45 секунд из-за скачивания base images и сборки, а команда об этом не знает, они решат, что деплой завис, и начнут паниковать — задокументированный cold start снимает эту неопределённость. Частое заблуждение — «раз у меня всё работает локально, значит и в capstone заработает» — но сравнение чек-листа week-21 с требованиями DevHub (список gaps в notes/capstone-prep.md) именно для того и нужно, чтобы найти пробелы заранее, а не в последний день недели 22, когда времени на исправление уже не будет. Mermaid-диаграмма и smoke-checklist, которые ты создаёшь сегодня, станут прямыми шаблонами для ARCHITECTURE.md и SMOKE_TEST.md капстоуна.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена регулярный smoke test — это то, что команды запускают сразу после каждого деплоя, ещё до того как объявить релиз завершённым: если базовый путь пользователя (login → основное действие → выход) не работает, откатывать деплой нужно немедленно, не дожидаясь жалоб реальных пользователей. Привычка писать такой чек-лист за 10 минут до того, как считать задачу «готовой», экономит часы разбора инцидентов в проде.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: smoke test + architecture diagram — входной билет в capstone неделю.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Smoke checklist в SMOKE_TEST.md: compose up → open app → login → CRUD task → refresh → persists
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Mermaid diagram в README: frontend, backend, db, volumes
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Замер cold start docker compose up --build — запиши время
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Проверь все env vars в .env.example
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Сравни week-21 с требованиями DevHub Capstone — что уже готово
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Список gaps для capstone в notes/capstone-prep.md
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Smoke test checklist пройден\n- [ ] Mermaid diagram в README\n- [ ] Все env vars в .env.example

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Smoke checklist в SMOKE_TEST.md: compose up → open app → login → CRUD task → refresh → persists
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Mermaid diagram в README: frontend, backend, db, volumes
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Замер cold start docker compose up --build — запиши время
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Устал — сделай коммит текущего прогресса с честным сообщением wip: и паузу 10 минут. Не геройствуй.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-21/git commit -m \"week 21 day 147: smoke test and architecture diagram\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поставь тег: git tag week-21-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Full-Stack Task Manager в Docker. Спецификация: docs/projects.md — неделя 21.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура monorepo

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        week-21/\n├── frontend/           # Vite React TS\n├── backend/            # Express or FastAPI\n├── docker-compose.yml\n├── docker-compose.dev.yml\n├── .env.example\n├── SMOKE_TEST.md\n└── README.md\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. React frontend + Express/FastAPI backend + PostgreSQL
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Auth (JWT из нед. 20), tasks CRUD через API
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. docker-compose.yml — db, backend, frontend
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Volumes, healthchecks, seed data, wait-for-db
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Dev и prod инструкции, architecture diagram
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии проекта

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • docker compose up --build — working app на localhost
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Данные переживают restart (named volume)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • CORS и VITE_API_URL корректны для docker network
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Healthcheck на db и /api/health на backend
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • SMOKE_TEST.md пройден без ошибок
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • README: architecture, env, dev vs prod commands
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Тег week-21-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Этот проект — прямой задел для DevHub Capstone: та же структура frontend/ + backend/ + docker-compose.yml.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Зачем Docker если можно npm start локально?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Чем image отличается от container?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Почему localhost внутри container не работает для host DB?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Что такое CORS и когда браузер блокирует запрос?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • docker-compose vs kubernetes — когда что (обзор)?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **Task Manager Docker** в `learning-log/week-21/`, осмысленная Git-история, тег `week-21-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nFull-stack в Docker Compose\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-21-day-141", "label": "День 141 (Пн): Связка Frontend + Backend"}, {"id": "week-21-day-142", "label": "День 142 (Вт): Единый API-контракт и обработка ошибок"}, {"id": "week-21-day-143", "label": "День 143 (Ср): Docker — основы"}, {"id": "week-21-day-144", "label": "День 144 (Чт): Docker для frontend и PostgreSQL"}, {"id": "week-21-day-145", "label": "День 145 (Пт): docker-compose — multi-service"}, {"id": "week-21-day-146", "label": "День 146 (Сб): Dev vs Prod конфигурация"}, {"id": "week-21-day-147", "label": "День 147 (Вс): E2E smoke test и ревью архитектуры"}, {"id": "week-21-project", "label": "Проект недели"}, {"id": "week-21-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-21-review", "label": "Проверь себя"}], "text": "Неделя 21: Full-Stack интеграция и Docker Цель недели: связать React-фронтенд с бэкендом и упаковать всё в Docker Compose. Литература: Docker Docs , docker-compose , Vite Env Проект недели: Task Manager Docker — React + API + PostgreSQL в docker-compose , healthchecks, seed. Git: папка learning-log/week-21/ , monorepo или два репо в одной папке; тег week-21-done . День 141 (Пн): Связка Frontend + Backend Время (полный): ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью Время (лайт): ~55м теория · ~1ч практика (MVP) · ~10м Git Связь с проектом: шаг к Task Manager Docker Теория Full-stack начинается там, где фронтенд и бэкенд встречаются в браузере. Same-origin policy: localhost:5173 (Vite) и localhost:3000 (API) — разные origins. Браузер блокирует cross-origin fetch без заголовков CORS от…"} \ No newline at end of file diff --git a/docs/weeks/22.json b/docs/weeks/22.json index a85c8de..74757d1 100644 --- a/docs/weeks/22.json +++ b/docs/weeks/22.json @@ -1 +1 @@ -{"id": "week-22", "title": "Capstone", "fullTitle": "Неделя 22: DevHub Capstone — финальный full-stack проект", "html": "

                                                                                                                                                                                                                        Неделя 22: DevHub Capstone — финальный full-stack проект

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: собрать, протестировать и задеплоить DevHub — единый capstone, объединяющий весь стек 22 недель обучения.\nЛитература: docs/projects.md — DevHub Capstone, Vercel Docs, Render Docs, GitHub Actions\nПроект недели: DevHub Capstone — персональная платформа разработчика: дашборд + заметки + задачи + GitHub API.\nGit: папка learning-log/week-22-capstone/, feature-ветки по дням 149–153; тег week-22-done + обновление GitHub Profile README.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не начинайте с нуля в последний день. Планируйте в день 148, кодите 149–153, деплой и портфолио — в день 154. Полная спецификация MVP, стека и критериев сдачи — в каталоге проектов.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 148 (Пн): Планирование DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DevHub Capstone — синтез 22 недель обучения. Не начинай код в последний день: день 148 — планирование, 149–153 — реализация, 154 — deploy и портфолио. Прочитай полную спецификацию в projects.md: концепция (дашборд + заметки + задачи + GitHub API), обязательный стек, MVP vs nice-to-have.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Scope control критичен: 7 дней, фиксированный MVP из 9 пунктов. WebSocket, kanban drag-and-drop, chat — после MVP. User stories формата «As a developer, I want…» с acceptance criteria превращают размытые идеи в проверяемые задачи.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура repo: frontend/, backend/, docker-compose.yml, .github/workflows/ci.yml. Выбери один backend: FastAPI (нед. 18) или Express (нед. 19). ER-диаграмма ≥ 5 сущностей, API endpoints list, page map React — артефакты до первой строки кода. Скопируй структуру week-21 как стартовую точку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: PLAN.md фиксирует scope; два backend одновременно — ловушка недели.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Прочитай весь раздел capstone и выпиши чеклист MVP (9 пунктов из projects.md)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Выбери backend: FastAPI (нед. 18) или Express (нед. 19) — один основной стек
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. User stories: минимум 10 штук (auth, tasks, notes, dashboard, profile, API, security, tests, docs)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. ER-диаграмма: users, tasks, notes, tags, note_tags — ≥ 5 сущностей со связями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. API endpoints list: /auth/*, /api/v1/tasks, /api/v1/notes, /api/v1/profile, /api/v1/dashboard
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Page map React: /login, /register, /dashboard, /tasks, /notes, /profile
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. GitHub repo week-22-capstone, README skeleton, GitHub Projects board
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        15. Скопируй структуру из week-21 как стартовую точку
                                                                                                                                                                                                                        16. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] MVP scope зафиксирован в PLAN.md — не расползается\n- [ ] ≥ 10 user stories с acceptance criteria\n- [ ] ER-диаграмма и API list в repo\n- [ ] Repo создан, ветка main + strategy feature branches

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Прочитай весь раздел capstone и выпиши чеклист MVP (9 пунктов из projects.md)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Выбери backend: FastAPI (нед. 18) или Express (нед. 19) — один основной стек
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. User stories: минимум 10 штук (auth, tasks, notes, dashboard, profile, API, security, tests, docs)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. ER-диаграмма: users, tasks, notes, tags, note_tags — ≥ 5 сущностей со связями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/git commit -m \"week 22 day 148: DevHub planning PLAN.md and ER diagram\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Scope creep: drag-and-drop kanban + WebSocket + chat в MVP
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Два backend одновременно — выбери один, второй только для сравнения в README
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 149 (Вт): Backend DevHub

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Backend DevHub — layered API: routers → services → repositories → PostgreSQL. Переиспользуй паттерны Library REST API (нед. 18) или Express Notes (нед. 19): APIRouter/Express Router, Pydantic/Zod validation, пагинация { items, total, page, size }, OpenAPI/Swagger.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Схема БД: users, tasks, notes, tags, note_tags — минимум 5 сущностей со связями. CRUD tasks с user_id FK; notes с markdown body и тегами many-to-many. GET /api/v1/dashboard/stats — агрегаты для виджетов. Пока без auth — заглушка user_id, auth на день 151.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Миграции: Alembic (FastAPI) или SQL scripts (Express). Seed: demo user + sample data для демо и тестов. .env.example: DATABASE_URL, JWT_SECRET, APP_ENV. God router на 500 строк — разбей по доменам. Пагинация с первого дня — иначе сломается на реальных данных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: backend capstone = CRUD + schema + seed + OpenAPI до auth layer.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Инициализируй backend/ — FastAPI или Express по выбору из дня 148
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Модели/таблицы: users, tasks, notes, tags, note_tags (many-to-many)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CRUD /api/v1/tasks: title, priority, status, deadline, user_id FK
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. CRUD /api/v1/notes: title, body (markdown), tags, search query param
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. GET /api/v1/dashboard/stats — count tasks by status, recent notes
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Swagger /docs (FastAPI) или OpenAPI export; пагинация { items, total, page, size }
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. schema.sql / Alembic migration + seed.sql с demo данными
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        15. .env.example: DATABASE_URL, JWT_SECRET, APP_ENV
                                                                                                                                                                                                                        16. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] ≥ 5 сущностей в БД со связями (см. критерии сдачи)\n- [ ] Tasks и Notes CRUD работают (пока без auth — заглушка user_id)\n- [ ] OpenAPI/Swagger актуален\n- [ ] Seed выполняется одной командой

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Инициализируй backend/ — FastAPI или Express по выбору из дня 148
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Модели/таблицы: users, tasks, notes, tags, note_tags (many-to-many)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CRUD /api/v1/tasks: title, priority, status, deadline, user_id FK
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. CRUD /api/v1/notes: title, body (markdown), tags, search query param
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/backend/git commit -m \"week 22 day 149: DevHub backend models and CRUD API\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • God router на 500 строк — разбей по доменам
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Нет пагинации — сломается на реальных данных
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 150 (Ср): Frontend DevHub (React + TypeScript)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Frontend DevHub собирает навыки Portfolio SPA (нед. 13) и React Dashboard (нед. 14). React 18+ TypeScript, React Router, Context или Zustand для глобального state. Структура: pages/, components/, hooks/, services/api.ts, types/. VITE_API_URL — base URL API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Четыре+ маршрута с Layout: /dashboard, /tasks, /notes, /profile. Shared UI kit: Button, Card, Spinner, ErrorMessage — консистентность. Loading / error / empty на каждой data-fetching странице — не «потом». Mobile-first layout для dashboard.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        services/api.ts — typed fetch wrapper; не fetch в каждом компоненте. Tasks: CRUD, фильтр status/priority. Notes: markdown textarea + preview, теги. Dashboard: виджеты статистики, placeholder GitHub repos. TypeScript strict, без any в api layer. Auth подключишь на день 151.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: один api.ts, три UI-состояния, shared components — фронтенд capstone в миниатюре.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm create vite@latest frontend -- --template react-ts
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. React Router: Layout + routes /dashboard, /tasks, /notes, /profile
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. services/api.ts — typed fetch wrapper (пока без auth token)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Dashboard: статистика задач (виджеты), placeholder для GitHub repos или погоды
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Tasks: список, create/edit form, фильтр по status/priority
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Notes: список с preview, markdown editor (textarea + preview), теги
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Profile: форма bio, avatar URL (пока mock)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        15. Shared UI: Button, Card, Spinner, ErrorMessage
                                                                                                                                                                                                                        16. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] 4+ маршрута с общим Layout\n- [ ] Tasks и Notes CRUD через API (без auth пока)\n- [ ] TypeScript strict, нет any в api layer\n- [ ] Loading и error states на всех data-fetching страницах

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm create vite@latest frontend -- --template react-ts
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. React Router: Layout + routes /dashboard, /tasks, /notes, /profile
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. services/api.ts — typed fetch wrapper (пока без auth token)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Dashboard: статистика задач (виджеты), placeholder для GitHub repos или погоды
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Код «магический» — объясни вслух каждый шаг как пятилетке. Где споткнулся — там дыра в понимании.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/frontend/git commit -m \"week 22 day 150: DevHub React TS pages and API client\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Fetch в каждом компоненте — один api.ts
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Забытый VITE_API_URL — API calls на undefined
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 151 (Чт): Auth — JWT end-to-end

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Auth end-to-end — обязательный MVP пункт. Переиспользуй Secure Notes (нед. 20): bcrypt/passlib, JWT, middleware на protected routes. Backend: POST /auth/register, POST /auth/login; все /api/v1/* требуют Authorization: Bearer. user_id из JWT payload — не из request body (IDOR уязвимость).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Frontend: AuthProvider, useAuth(), /login, /register, protected routes с redirect. api.ts — auto Bearer header, logout on 401. Rate limit на login, CORS whitelist, helmet — из недели 20. Начни SECURITY.md с OWASP checklist.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        E2E manual test: register → login → create task → logout → login → task visible. User A не видит данные User B → 403. JWT secret в git — rotate немедленно. Задокументируй выбор localStorage vs httpOnly cookie.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: auth — сквозной слой; user_id только из verified JWT.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Backend auth: register, login, JWT middleware на все protected routes
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Привяжи tasks и notes к user_id из token — миграция если нужно
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. React: /login, /register pages; AuthProvider + useAuth()
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Protected routes — redirect на /login без token
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. api.ts — автоматический Authorization: Bearer, logout on 401
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Rate limit на /auth/login, helmet/CORS настроены
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Начни SECURITY.md — OWASP checklist (из нед. 20)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        15. E2E manual: register → login → create task → logout → login → task visible
                                                                                                                                                                                                                        16. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Auth end-to-end работает (см. критерии сдачи)\n- [ ] User A не видит данные User B\n- [ ] 401 без token, 403 на чужие ресурсы\n- [ ] SECURITY.md начат

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Backend auth: register, login, JWT middleware на все protected routes
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Привяжи tasks и notes к user_id из token — миграция если нужно
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. React: /login, /register pages; AuthProvider + useAuth()
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Protected routes — redirect на /login без token
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/git commit -m \"week 22 day 151: DevHub JWT auth frontend backend\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • user_id из body вместо JWT — IDOR уязвимость
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • JWT secret в git — rotate немедленно
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 152 (Пт): Docker — локальный full-stack

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Docker Compose — критерий сдачи capstone: docker compose up поднимает всё локально. Переиспользуй Task Manager Docker (нед. 21): services db, backend, frontend; healthchecks; named volumes; entrypoint wait-for-db → migrate → seed → start.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Multi-stage frontend Dockerfile (nginx + dist). Backend Dockerfile slim. VITE_API_URL как build arg — в docker network указывает на backend service, не localhost. .dockerignore в обоих папках. ARCHITECTURE.md с Mermaid: client → API → DB → volumes.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        README «запуск за 5 команд»: clone → copy .envdocker compose up --build → open browser. Backend стартует до PG — healthcheck + retry в entrypoint. Полный smoke: auth + CRUD через dockerized frontend.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: docker compose — часть MVP; VITE_API_URL для docker network, не localhost.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. docker-compose.yml: postgres + backend + frontend (nginx)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Backend Dockerfile, Frontend multi-stage Dockerfile
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Healthcheck на db (pg_isready) и backend (/api/health)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Entrypoint: wait-for-db → migrate → seed → start
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. .dockerignore в frontend и backend
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. docker compose up --build — полный smoke test
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. ARCHITECTURE.md — Mermaid diagram (client → API → DB → volumes)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        15. Обнови README: «запуск за 5 команд» (клон → env → compose up → open browser)
                                                                                                                                                                                                                        16. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] docker compose up поднимает всё локально (критерии сдачи)\n- [ ] Auth + CRUD работают через dockerized frontend\n- [ ] ARCHITECTURE.md с диаграммой\n- [ ] README local setup ≤ 5 команд

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. docker-compose.yml: postgres + backend + frontend (nginx)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Backend Dockerfile, Frontend multi-stage Dockerfile
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Healthcheck на db (pg_isready) и backend (/api/health)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Entrypoint: wait-for-db → migrate → seed → start
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/git commit -m \"week 22 day 152: DevHub docker-compose and ARCHITECTURE.md\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Backend стартует до PG — добавь healthcheck и retry
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • VITE_API_URL указывает на localhost внутри docker network
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 153 (Сб): Тесты и CI

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~55м теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Quality gate capstone: pytest ≥ 15, Vitest ≥ 12, ESLint без ошибок, CI green on push. Тесты из MVP: auth flow, CRUD tasks, 401 без token, 403 cross-user. GitHub Actions: job backend (postgres service + pytest) + job frontend (vitest + lint). Badge CI в README.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Test DB isolation — postgres service в CI или SQLite in-memory; не production. Flaky tests из shared state — изолируй fixtures с rollback. npm audit / pip audit — зафиксируй в SECURITY.md. Auth flow должен быть покрыт тестами, не только manual E2E.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Локально все тесты зелёные перед push. CI без postgres service — тесты падают на GitHub. Это последний рубеж перед deploy: если CI красный, deploy откладывается.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: CI green — критерий сдачи; тесты на auth и isolation обязательны.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Backend pytest: auth (register, login, 401), tasks CRUD, notes CRUD, 403 cross-user — ≥ 15 тестов
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Frontend Vitest: Login form, ProtectedRoute, TaskList, NoteEditor — ≥ 12 тестов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. ESLint + npm run lint в frontend; ruff или flake8 в backend (опционально)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. .github/workflows/ci.yml: job backend (postgres service, pytest) + job frontend (vitest, lint)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Badge CI в README
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. npm audit / pip audit — зафиксируй в SECURITY.md
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Все тесты зелёные локально перед push
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] pytest ≥ 15, Vitest ≥ 12 — все проходят\n- [ ] CI green on push\n- [ ] ESLint без ошибок (или задокументированные исключения)\n- [ ] Auth flow покрыт тестами

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Backend pytest: auth (register, login, 401), tasks CRUD, notes CRUD, 403 cross-user — ≥ 15 тестов
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Frontend Vitest: Login form, ProtectedRoute, TaskList, NoteEditor — ≥ 12 тестов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. ESLint + npm run lint в frontend; ruff или flake8 в backend (опционально)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. .github/workflows/ci.yml: job backend (postgres service, pytest) + job frontend (vitest, lint)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/git commit -m \"week 22 day 153: DevHub tests and GitHub Actions CI\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • CI без postgres service — тесты падают на GitHub
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Flaky tests из-за shared state — изолируй fixtures
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 154 (Вс): Deploy, портфолио и финальное ревью

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~1ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~25м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Финальный день — deploy, портфолио и рефлексия. Frontend → Vercel/Netlify (root frontend/, VITE_API_URL = production API). Backend + managed PostgreSQL → Render/Railway/Neon. После deploy: обнови CORS для Vercel domain, rotate JWT_SECRET если был в git, env vars в cloud dashboard.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Live HTTPS demo — критерий сдачи: register → login → CRUD в браузере. FINAL_REVIEW.md: что узнал за 22 недели, что бы сделал иначе. GitHub Profile README — таблица всех 22 проектов со ссылками. README DevHub: badges, demo URL, screenshots, docker setup, architecture.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Free tier cold start 30–60 сек — документируй. Забытый CORS update — API works in curl, fails в browser на Vercel. 2-минутный pitch DevHub — устная репетиция архитектуры. Тег week-22-done — финиш роадмапа. Поздравляем: ты junior full-stack ready.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: deploy + FINAL_REVIEW + profile README — три грани финиша capstone.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Deploy backend: Render/Railway — connect repo, DATABASE_URL + JWT_SECRET
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Deploy DB: managed PostgreSQL, run migrations + seed
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Deploy frontend: Vercel — root frontend/, VITE_API_URL = production API URL
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Update CORS — добавь Vercel domain
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь live demo: HTTPS, register → login → CRUD
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. README: badges, live demo URLs, screenshots/GIF, tech stack
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. FINAL_REVIEW.md: что узнал, что бы сделал иначе
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        15. GitHub Profile README: таблица 22 проектов (как в projects.md)
                                                                                                                                                                                                                        16. \n
                                                                                                                                                                                                                        17. Резюме PDF с live links; 2-мин pitch DevHub
                                                                                                                                                                                                                        18. \n
                                                                                                                                                                                                                        19. Пройди ревью-чеклист — ≥ 80% уверенных ответов
                                                                                                                                                                                                                        20. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Live HTTPS demo (frontend + API)\n- [ ] FINAL_REVIEW.md заполнен\n- [ ] GitHub profile README обновлён со ссылками на все 22 проекта\n- [ ] README DevHub — demo link, docker setup, architecture, tests

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Deploy backend: Render/Railway — connect repo, DATABASE_URL + JWT_SECRET
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Deploy DB: managed PostgreSQL, run migrations + seed
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Deploy frontend: Vercel — root frontend/, VITE_API_URL = production API URL
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Update CORS — добавь Vercel domain
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь live demo: HTTPS, register → login → CRUD
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/git commit -m \"week 22 day 154: DevHub deploy portfolio FINAL_REVIEW\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поставь тег: git tag week-22-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Push tags: git push origin main --tags
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Забытый CORS update — API works in curl, fails in browser on Vercel
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Free tier cold start 30–60 сек — документируй в README
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DevHub Capstone — финальный проект роадмапа

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Полная спецификация: docs/projects.md — Неделя 22, DevHub Capstone

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Концепция

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Персональная платформа разработчика: дашборд + заметки + задачи + интеграция с GitHub API (или виджет погоды) — production full-stack app.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Обязательный стек

                                                                                                                                                                                                                        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                                                                                                                                                                        СлойТехнологии
                                                                                                                                                                                                                        FrontendReact 18+, TypeScript, React Router, Context/Zustand
                                                                                                                                                                                                                        BackendFastAPI или Express (один основной)
                                                                                                                                                                                                                        БДPostgreSQL, миграции, seed
                                                                                                                                                                                                                        AuthJWT (register/login), protected routes
                                                                                                                                                                                                                        InfraDocker Compose локально, CI (GitHub Actions)
                                                                                                                                                                                                                        DeployFrontend → Vercel/Netlify, Backend + DB → Render/Railway/Neon
                                                                                                                                                                                                                        Qualitypytest ≥ 15, Vitest ≥ 12, ESLint, README, .env.example
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции MVP

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        См. projects.md: Auth, Tasks, Notes, Dashboard, Profile, API, Security, Tests, Docs.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура репозитория

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        week-22-capstone/\n├── frontend/\n├── backend/\n├── docker-compose.yml\n├── .github/workflows/ci.yml\n├── SECURITY.md\n├── ARCHITECTURE.md\n├── FINAL_REVIEW.md\n└── README.md\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии сдачи

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Live HTTPS demo (frontend + API)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • docker compose up поднимает всё локально
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Auth end-to-end работает
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • ≥ 5 сущностей в БД со связями
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • CI green on push
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • FINAL_REVIEW.md заполнен
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • GitHub profile README — ссылки на все 22 проекта
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Тег week-22-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Связь с проектами 13–21

                                                                                                                                                                                                                        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                                                                                                                                                                        НеделяПереиспользуешь
                                                                                                                                                                                                                        14 — DashboardUI виджеты, fetch
                                                                                                                                                                                                                        18/19 — APICRUD, Swagger
                                                                                                                                                                                                                        20 — Secure NotesJWT, тесты
                                                                                                                                                                                                                        21 — Dockercompose, monorepo
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Nice-to-have: projects.md.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • HTML/CSS: block vs inline, Flexbox vs Grid?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • JS: замыкание, Event Loop, var/let/const?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • React: key, useState vs useEffect?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Python: Big O, магические методы, venv?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • SQL: JOIN, индексы, injection?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Node: middleware, connection pool?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Full-Stack: REST, CORS, JWT, Docker?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • DevHub: архитектура за 2 минуты?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        80%+ уверенных ответов — ты готов к junior full-stack. Поздравляем с завершением 22-недельного роадмапа!

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **DevHub Capstone** в `learning-log/week-22/`, осмысленная Git-история, тег `week-22-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nProduction capstone: DevHub full-stack\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-22-day-148", "label": "День 148 (Пн): Планирование DevHub Capstone"}, {"id": "week-22-day-149", "label": "День 149 (Вт): Backend DevHub"}, {"id": "week-22-day-150", "label": "День 150 (Ср): Frontend DevHub (React + TypeScript)"}, {"id": "week-22-day-151", "label": "День 151 (Чт): Auth — JWT end-to-end"}, {"id": "week-22-day-152", "label": "День 152 (Пт): Docker — локальный full-stack"}, {"id": "week-22-day-153", "label": "День 153 (Сб): Тесты и CI"}, {"id": "week-22-day-154", "label": "День 154 (Вс): Deploy, портфолио и финальное ревью"}, {"id": "week-22-project", "label": "Проект недели"}, {"id": "week-22-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-22-review", "label": "Проверь себя"}], "text": "Неделя 22: DevHub Capstone — финальный full-stack проект Цель недели: собрать, протестировать и задеплоить DevHub — единый capstone, объединяющий весь стек 22 недель обучения. Литература: docs/projects.md — DevHub Capstone , Vercel Docs , Render Docs , GitHub Actions Проект недели: DevHub Capstone — персональная платформа разработчика: дашборд + заметки + задачи + GitHub API. Git: папка learning-log/week-22-capstone/ , feature-ветки по дням 149–153; тег week-22-done + обновление GitHub Profile README. Не начинайте с нуля в последний день. Планируйте в день 148, кодите 149–153, деплой и портфолио — в день 154. Полная спецификация MVP, стека и критериев сдачи — в каталоге проектов . День 148 (Пн): Планирование DevHub Capstone Время (полный): ~1ч теория · ~3.5ч практика · ~15м Git · ~45м ревь…"} \ No newline at end of file +{"id": "week-22", "title": "Capstone", "fullTitle": "Неделя 22: DevHub Capstone — финальный full-stack проект", "html": "

                                                                                                                                                                                                                        Неделя 22: DevHub Capstone — финальный full-stack проект

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Цель недели: собрать, протестировать и задеплоить DevHub — единый capstone, объединяющий весь стек 22 недель обучения.\nЛитература: docs/projects.md — DevHub Capstone, Vercel Docs, Render Docs, GitHub Actions\nПроект недели: DevHub Capstone — персональная платформа разработчика: дашборд + заметки + задачи + GitHub API.\nGit: папка learning-log/week-22-capstone/, feature-ветки по дням 149–153; тег week-22-done + обновление GitHub Profile README.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Не начинайте с нуля в последний день. Планируйте в день 148, кодите 149–153, деплой и портфолио — в день 154. Полная спецификация MVP, стека и критериев сдачи — в каталоге проектов.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 148 (Пн): Планирование DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DevHub Capstone — синтез 22 недель обучения. Не начинай код в последний день: день 148 — планирование, 149–153 — реализация, 154 — deploy и портфолио. Прочитай полную спецификацию в projects.md: концепция (дашборд + заметки + задачи + GitHub API), обязательный стек, MVP vs nice-to-have.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Scope control критичен: 7 дней, фиксированный MVP из 9 пунктов. WebSocket, kanban drag-and-drop, chat — после MVP. User stories формата «As a developer, I want…» с acceptance criteria превращают размытые идеи в проверяемые задачи.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура repo: frontend/, backend/, docker-compose.yml, .github/workflows/ci.yml. Выбери один backend: FastAPI (нед. 18) или Express (нед. 19). ER-диаграмма ≥ 5 сущностей, API endpoints list, page map React — артефакты до первой строки кода. Скопируй структуру week-21 как стартовую точку.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: планирование — это карта перед походом, а не бюрократия, отнимающая время от «настоящей» работы. Час, потраченный на PLAN.md и ER-диаграмму, экономит часы блуждания в коде посреди недели, когда неясно, зачем нужна ещё одна таблица или откуда взялся баг в связях данных. Для junior-разработчика умение декомпозировать нечёткое задание («сделай платформу разработчика») на конкретные user stories с acceptance criteria — один из самых ценных навыков, который отличает исполнителя от инженера, способного работать самостоятельно.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример цены отсутствия плана: команды, которые прыгают в код без ER-диаграммы, типично обнаруживают на четвёртый день, что забыли связь many-to-many между notes и tags, и переделывают миграции задним числом, теряя данные тестового прогона. Частое заблуждение — «за 7 дней успею и kanban с drag-and-drop, и WebSocket-чат, и weather widget» — это классический scope creep, который гарантированно оставляет MVP недоделанным; профессиональные команды сначала фиксируют MVP, а «хотелки» уходят в backlog. Артефакты сегодняшнего дня — PLAN.md, ER-диаграмма, page map — не формальность для галочки, а рабочие документы, на которые ты будешь ссылаться каждый день оставшейся недели.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена этот же принцип масштабируется на уровень целых команд: перед стартом крупной фичи инженерные команды пишут design doc или RFC именно по той же причине — зафиксировать scope и получить обратную связь до того, как написана первая строка кода, а не после недели работы впустую. Умение написать короткий, но конкретный план — навык, который пригодится далеко за пределами этого одного проекта.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: PLAN.md фиксирует scope; два backend одновременно — ловушка недели.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Прочитай весь раздел capstone и выпиши чеклист MVP (9 пунктов из projects.md)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Выбери backend: FastAPI (нед. 18) или Express (нед. 19) — один основной стек
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. User stories: минимум 10 штук (auth, tasks, notes, dashboard, profile, API, security, tests, docs)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. ER-диаграмма: users, tasks, notes, tags, note_tags — ≥ 5 сущностей со связями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. API endpoints list: /auth/*, /api/v1/tasks, /api/v1/notes, /api/v1/profile, /api/v1/dashboard
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Page map React: /login, /register, /dashboard, /tasks, /notes, /profile
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. GitHub repo week-22-capstone, README skeleton, GitHub Projects board
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        15. Скопируй структуру из week-21 как стартовую точку
                                                                                                                                                                                                                        16. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] MVP scope зафиксирован в PLAN.md — не расползается\n- [ ] ≥ 10 user stories с acceptance criteria\n- [ ] ER-диаграмма и API list в repo\n- [ ] Repo создан, ветка main + strategy feature branches

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Прочитай весь раздел capstone и выпиши чеклист MVP (9 пунктов из projects.md)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Выбери backend: FastAPI (нед. 18) или Express (нед. 19) — один основной стек
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. User stories: минимум 10 штук (auth, tasks, notes, dashboard, profile, API, security, tests, docs)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. ER-диаграмма: users, tasks, notes, tags, note_tags — ≥ 5 сущностей со связями
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/git commit -m \"week 22 day 148: DevHub planning PLAN.md and ER diagram\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Scope creep: drag-and-drop kanban + WebSocket + chat в MVP
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Два backend одновременно — выбери один, второй только для сравнения в README
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 149 (Вт): Backend DevHub

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Backend DevHub — layered API: routers → services → repositories → PostgreSQL. Переиспользуй паттерны Library REST API (нед. 18) или Express Notes (нед. 19): APIRouter/Express Router, Pydantic/Zod validation, пагинация { items, total, page, size }, OpenAPI/Swagger.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Схема БД: users, tasks, notes, tags, note_tags — минимум 5 сущностей со связями. CRUD tasks с user_id FK; notes с markdown body и тегами many-to-many. GET /api/v1/dashboard/stats — агрегаты для виджетов. Пока без auth — заглушка user_id, auth на день 151.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Миграции: Alembic (FastAPI) или SQL scripts (Express). Seed: demo user + sample data для демо и тестов. .env.example: DATABASE_URL, JWT_SECRET, APP_ENV. God router на 500 строк — разбей по доменам. Пагинация с первого дня — иначе сломается на реальных данных.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: layered architecture (routers → services → repositories) — это как конвейер: каждый слой отвечает за одну зону ответственности, и изменение в одной зоне (например, смена ORM) не требует переписывать HTTP-обработчики. Для junior backend-разработчика способность структурировать API не «одним файлом на 2000 строк», а по доменам — прямой признак, который ревьюер видит за первые пять минут просмотра репозитория на собеседовании или в портфолио.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: GET /api/v1/dashboard/stats выглядит как простой endpoint, но требует агрегации из нескольких таблиц (count tasks by status, recent notes) — если логику агрегации не вынести в отдельный service, она расползётся дублированием в разных местах роутера при добавлении новых виджетов. Частое заблуждение — «auth — это скучная обвязка, сделаю CRUD, а потом уже security» — на самом деле откладывание auth на день 151 осознанно: это позволяет сосредоточиться на форме данных сегодня, но заглушка user_id должна быть явной и задокументированной, а не забытой лазейкой. Сегодняшняя схема БД (users, tasks, notes, tags, note_tags) — это тот самый набор ≥5 сущностей, который прямо проверяется в критериях сдачи capstone, поэтому качество миграций и seed данных сейчас определяет, насколько гладко пройдёт остаток недели.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена OpenAPI/Swagger документация, которую генерирует FastAPI автоматически (или которую нужно написать вручную для Express), — это не просто «красивая страница», а контракт, на который будет опираться frontend-разработчик (день 150) при написании типов; расхождение между реальным API и документацией — источник багов интеграции, которые сложно диагностировать без явного сравнения запроса и ответа.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: backend capstone = CRUD + schema + seed + OpenAPI до auth layer.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Инициализируй backend/ — FastAPI или Express по выбору из дня 148
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Модели/таблицы: users, tasks, notes, tags, note_tags (many-to-many)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CRUD /api/v1/tasks: title, priority, status, deadline, user_id FK
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. CRUD /api/v1/notes: title, body (markdown), tags, search query param
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. GET /api/v1/dashboard/stats — count tasks by status, recent notes
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Swagger /docs (FastAPI) или OpenAPI export; пагинация { items, total, page, size }
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. schema.sql / Alembic migration + seed.sql с demo данными
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        15. .env.example: DATABASE_URL, JWT_SECRET, APP_ENV
                                                                                                                                                                                                                        16. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] ≥ 5 сущностей в БД со связями (см. критерии сдачи)\n- [ ] Tasks и Notes CRUD работают (пока без auth — заглушка user_id)\n- [ ] OpenAPI/Swagger актуален\n- [ ] Seed выполняется одной командой

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Инициализируй backend/ — FastAPI или Express по выбору из дня 148
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Модели/таблицы: users, tasks, notes, tags, note_tags (many-to-many)
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. CRUD /api/v1/tasks: title, priority, status, deadline, user_id FK
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. CRUD /api/v1/notes: title, body (markdown), tags, search query param
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Тесты/валидация красные — сначала один failing case, почини его, только потом следующий.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/backend/git commit -m \"week 22 day 149: DevHub backend models and CRUD API\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • God router на 500 строк — разбей по доменам
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Нет пагинации — сломается на реальных данных
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 150 (Ср): Frontend DevHub (React + TypeScript)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Frontend DevHub собирает навыки Portfolio SPA (нед. 13) и React Dashboard (нед. 14). React 18+ TypeScript, React Router, Context или Zustand для глобального state. Структура: pages/, components/, hooks/, services/api.ts, types/. VITE_API_URL — base URL API.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Четыре+ маршрута с Layout: /dashboard, /tasks, /notes, /profile. Shared UI kit: Button, Card, Spinner, ErrorMessage — консистентность. Loading / error / empty на каждой data-fetching странице — не «потом». Mobile-first layout для dashboard.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        services/api.ts — typed fetch wrapper; не fetch в каждом компоненте. Tasks: CRUD, фильтр status/priority. Notes: markdown textarea + preview, теги. Dashboard: виджеты статистики, placeholder GitHub repos. TypeScript strict, без any в api layer. Auth подключишь на день 151.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: frontend capstone — это не новый набор навыков, а синтез уже отработанных паттернов (Portfolio SPA, React Dashboard) в одном большом приложении — организация pages/hooks/services/types масштабирует то, что раньше умещалось в пару файлов. Для junior frontend-роли способность держать типизацию строгой (TypeScript strict, без any в api layer) на растущем проекте — именно то, что отличает код, готовый к сопровождению командой, от одноразового прототипа.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: без shared UI kit (Button, Card, Spinner, ErrorMessage) четыре страницы (dashboard, tasks, notes, profile) неизбежно разъедутся визуально — один разработчик сделает spinner в виде текста «Loading...», другой — CSS-анимацию, и продукт будет выглядеть несобранным, даже если код работает. Частое заблуждение — «auth подключу позже, сейчас не важно» — верно для порядка работы, но опасно, если забыть спроектировать api.ts так, чтобы Bearer-заголовок можно было добавить одной строкой на день 151, а не переписывать весь fetch-слой заново. Четыре маршрута с общим Layout, которые ты собираешь сегодня, — это тот самый page map, который завтра обрастёт защищёнными маршрутами, а через несколько дней — Docker-инфраструктурой для деплоя.

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: один api.ts, три UI-состояния, shared components — фронтенд capstone в миниатюре.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm create vite@latest frontend -- --template react-ts
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. React Router: Layout + routes /dashboard, /tasks, /notes, /profile
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. services/api.ts — typed fetch wrapper (пока без auth token)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Dashboard: статистика задач (виджеты), placeholder для GitHub repos или погоды
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Tasks: список, create/edit form, фильтр по status/priority
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Notes: список с preview, markdown editor (textarea + preview), теги
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Profile: форма bio, avatar URL (пока mock)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        15. Shared UI: Button, Card, Spinner, ErrorMessage
                                                                                                                                                                                                                        16. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] 4+ маршрута с общим Layout\n- [ ] Tasks и Notes CRUD через API (без auth пока)\n- [ ] TypeScript strict, нет any в api layer\n- [ ] Loading и error states на всех data-fetching страницах

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. npm create vite@latest frontend -- --template react-ts
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. React Router: Layout + routes /dashboard, /tasks, /notes, /profile
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. services/api.ts — typed fetch wrapper (пока без auth token)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Dashboard: статистика задач (виджеты), placeholder для GitHub repos или погоды
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/frontend/git commit -m \"week 22 day 150: DevHub React TS pages and API client\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Fetch в каждом компоненте — один api.ts
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Забытый VITE_API_URL — API calls на undefined
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 151 (Чт): Auth — JWT end-to-end

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Auth end-to-end — обязательный MVP пункт. Переиспользуй Secure Notes (нед. 20): bcrypt/passlib, JWT, middleware на protected routes. Backend: POST /auth/register, POST /auth/login; все /api/v1/* требуют Authorization: Bearer. user_id из JWT payload — не из request body (IDOR уязвимость).

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Frontend: AuthProvider, useAuth(), /login, /register, protected routes с redirect. api.ts — auto Bearer header, logout on 401. Rate limit на login, CORS whitelist, helmet — из недели 20. Начни SECURITY.md с OWASP checklist.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        E2E manual test: register → login → create task → logout → login → task visible. User A не видит данные User B → 403. JWT secret в git — rotate немедленно. Задокументируй выбор localStorage vs httpOnly cookie.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: auth в capstone — не отдельная фича, а сквозной слой, который пронизывает буквально каждый существующий endpoint и компонент — именно поэтому его добавляют после того, как CRUD уже работает, а не в начале, чтобы не отлаживать две сложные вещи одновременно. Для нанимающего junior full-stack инженера способность интегрировать auth end-to-end в уже существующую кодовую базу без переписывания архитектуры с нуля — куда более реалистичный сценарий работы, чем стартовать проект «с чистого листа».

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример риска: если миграция привязки tasks/notes к user_id сделана небрежно (например, дефолтное значение user_id = 1 для старых записей), в проде это создаст ситуацию, где новый пользователь внезапно видит демо-данные предыдущего — классическая ошибка, которую тестовый прогон «user A не видит данные user B» обязан поймать. Частое заблуждение — «раз я использую JWT, IDOR мне не грозит» — сам факт наличия токена не защищает, если backend всё равно читает user_id из тела запроса вместо payload токена; уязвимость возникает именно в этой конкретной строчке кода, а не в отсутствии JWT вообще. Auth end-to-end, который ты собираешь сегодня, — последний функциональный кирпич MVP перед инфраструктурными днями (Docker, тесты, деплой), поэтому качество этого дня определяет, будет ли остаток недели про полировку или про латание дыр в безопасности.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена стоит помнить: SECURITY.md, который ты начинаешь сегодня, — живой документ, а не разовый чеклист. В реальных компаниях подобные документы обновляются при каждом security review и служат доказательством due diligence перед аудиторами или партнёрами — привычка вести такую документацию с первого капстоун-проекта переносится в профессиональную практику без переучивания.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: auth — сквозной слой; user_id только из verified JWT.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Backend auth: register, login, JWT middleware на все protected routes
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Привяжи tasks и notes к user_id из token — миграция если нужно
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. React: /login, /register pages; AuthProvider + useAuth()
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Protected routes — redirect на /login без token
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. api.ts — автоматический Authorization: Bearer, logout on 401
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. Rate limit на /auth/login, helmet/CORS настроены
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Начни SECURITY.md — OWASP checklist (из нед. 20)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        15. E2E manual: register → login → create task → logout → login → task visible
                                                                                                                                                                                                                        16. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Auth end-to-end работает (см. критерии сдачи)\n- [ ] User A не видит данные User B\n- [ ] 401 без token, 403 на чужие ресурсы\n- [ ] SECURITY.md начат

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Backend auth: register, login, JWT middleware на все protected routes
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Привяжи tasks и notes к user_id из token — миграция если нужно
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. React: /login, /register pages; AuthProvider + useAuth()
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Protected routes — redirect на /login без token
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Слишком много концептов сразу — вернись к одному примеру из теории и повтори его руками, меняя имена.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/git commit -m \"week 22 day 151: DevHub JWT auth frontend backend\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • user_id из body вместо JWT — IDOR уязвимость
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • JWT secret в git — rotate немедленно
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 152 (Пт): Docker — локальный full-stack

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Docker Compose — критерий сдачи capstone: docker compose up поднимает всё локально. Переиспользуй Task Manager Docker (нед. 21): services db, backend, frontend; healthchecks; named volumes; entrypoint wait-for-db → migrate → seed → start.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Multi-stage frontend Dockerfile (nginx + dist). Backend Dockerfile slim. VITE_API_URL как build arg — в docker network указывает на backend service, не localhost. .dockerignore в обоих папках. ARCHITECTURE.md с Mermaid: client → API → DB → volumes.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        README «запуск за 5 команд»: clone → copy .envdocker compose up --build → open browser. Backend стартует до PG — healthcheck + retry в entrypoint. Полный smoke: auth + CRUD через dockerized frontend.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: docker compose up для целого capstone — это финальная репетиция перед premiere: если что-то не заводится в контейнерах, лучше узнать это сегодня, а не в день деплоя, когда времени на диагностику почти не останется. Для оценки готовности к junior-позиции воспроизводимость окружения («работает не только у меня») — один из первых критериев, которые технический ревьюер портфолио проверяет буквально за одну команду docker compose up --build.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: VITE_API_URL — build-time переменная, поэтому её нельзя просто передать в docker run как runtime env — если её значение зашито на localhost во время npm run build внутри Docker, production-сборка frontend будет пытаться достучаться до localhost из браузера пользователя, а не до реального backend, и все запросы будут падать молча. Частое заблуждение — «раз локально все три сервиса работают по отдельности, вместе тоже заработают» — но именно network-конфигурация (hostname backend вместо localhost, healthcheck на PostgreSQL) чаще всего ломается при первой сборке compose-стека. ARCHITECTURE.md с Mermaid-диаграммой, который ты создаёшь сегодня, станет частью финального README и будет тем документом, который ревьюер или интервьюер откроет первым, чтобы за 30 секунд понять устройство твоего DevHub.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена «запуск за 5 команд» в README — это не про красоту, а про снижение барьера для onboarding: чем больше шагов и недокументированных предположений («у тебя же уже установлен Postgres 16, да?») требует локальный запуск, тем меньше шанс, что коллега, ревьюер или рекрутер вообще дойдут до того, чтобы попробовать проект — большинство просто закроют вкладку после первой непонятной ошибки.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: docker compose — часть MVP; VITE_API_URL для docker network, не localhost.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. docker-compose.yml: postgres + backend + frontend (nginx)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Backend Dockerfile, Frontend multi-stage Dockerfile
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Healthcheck на db (pg_isready) и backend (/api/health)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Entrypoint: wait-for-db → migrate → seed → start
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. .dockerignore в frontend и backend
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. docker compose up --build — полный smoke test
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. ARCHITECTURE.md — Mermaid diagram (client → API → DB → volumes)
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        15. Обнови README: «запуск за 5 команд» (клон → env → compose up → open browser)
                                                                                                                                                                                                                        16. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] docker compose up поднимает всё локально (критерии сдачи)\n- [ ] Auth + CRUD работают через dockerized frontend\n- [ ] ARCHITECTURE.md с диаграммой\n- [ ] README local setup ≤ 5 команд

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. docker-compose.yml: postgres + backend + frontend (nginx)
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Backend Dockerfile, Frontend multi-stage Dockerfile
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Healthcheck на db (pg_isready) и backend (/api/health)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Entrypoint: wait-for-db → migrate → seed → start
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/git commit -m \"week 22 day 152: DevHub docker-compose and ARCHITECTURE.md\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Backend стартует до PG — добавь healthcheck и retry
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • VITE_API_URL указывает на localhost внутри docker network
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 153 (Сб): Тесты и CI

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Quality gate capstone: pytest ≥ 15, Vitest ≥ 12, ESLint без ошибок, CI green on push. Тесты из MVP: auth flow, CRUD tasks, 401 без token, 403 cross-user. GitHub Actions: job backend (postgres service + pytest) + job frontend (vitest + lint). Badge CI в README.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Test DB isolation — postgres service в CI или SQLite in-memory; не production. Flaky tests из shared state — изолируй fixtures с rollback. npm audit / pip audit — зафиксируй в SECURITY.md. Auth flow должен быть покрыт тестами, не только manual E2E.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Локально все тесты зелёные перед push. CI без postgres service — тесты падают на GitHub. Это последний рубеж перед deploy: если CI красный, deploy откладывается.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: quality gate — это шлагбаум, который физически не пускает недоделанный код дальше, а не вежливая рекомендация. Тесты на auth flow и cross-user isolation (403) — не для галочки количества, а потому что именно эти сценарии чаще всего ломаются при рефакторинге и именно они наносят максимальный репутационный ущерб, если баг просочится в прод. Для junior-кандидата зелёный CI badge на GitHub рядом с ≥15 backend и ≥12 frontend тестами — конкретное, проверяемое доказательство инженерной дисциплины, которое весит больше любых слов в резюме.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример: postgres service в GitHub Actions должен быть объявлен явно в workflow — если локально тесты используют реальный Postgres, а в CI забыли добавить сервис, тесты будут падать с connection refused именно на GitHub, хотя «на моей машине всё зелёное»; это одна из самых частых причин красного CI у новичков. Частое заблуждение — «раз тесты проходят локально один раз, в CI тоже пройдут» — flaky tests из-за shared state (например, два теста создают пользователя с одинаковым email) проявляются именно в CI, где тесты могут выполняться в другом порядке или параллельно. Green CI, который ты добиваешься сегодня, — формальный шлюз перед деплоем: день 154 начинается только если этот шлагбаум поднят.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Для продакшена ESLint без ошибок — минимальная, но обязательная планка стиля: она не заменяет тесты, но ловит целый класс проблем до code review (неиспользуемые переменные, потенциальные null-referenced, несогласованный стиль) и экономит время ревьюера на комментарии вроде «убери console.log». Badge CI в README — маленькая деталь, которая на практике заметно повышает доверие к репозиторию при первом взгляде.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: CI green — критерий сдачи; тесты на auth и isolation обязательны.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Backend pytest: auth (register, login, 401), tasks CRUD, notes CRUD, 403 cross-user — ≥ 15 тестов
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Frontend Vitest: Login form, ProtectedRoute, TaskList, NoteEditor — ≥ 12 тестов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. ESLint + npm run lint в frontend; ruff или flake8 в backend (опционально)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. .github/workflows/ci.yml: job backend (postgres service, pytest) + job frontend (vitest, lint)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Badge CI в README
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. npm audit / pip audit — зафиксируй в SECURITY.md
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. Все тесты зелёные локально перед push
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] pytest ≥ 15, Vitest ≥ 12 — все проходят\n- [ ] CI green on push\n- [ ] ESLint без ошибок (или задокументированные исключения)\n- [ ] Auth flow покрыт тестами

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Backend pytest: auth (register, login, 401), tasks CRUD, notes CRUD, 403 cross-user — ≥ 15 тестов
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Frontend Vitest: Login form, ProtectedRoute, TaskList, NoteEditor — ≥ 12 тестов
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. ESLint + npm run lint в frontend; ruff или flake8 в backend (опционально)
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. .github/workflows/ci.yml: job backend (postgres service, pytest) + job frontend (vitest, lint)
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

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

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/git commit -m \"week 22 day 153: DevHub tests and GitHub Actions CI\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • CI без postgres service — тесты падают на GitHub
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Flaky tests из-за shared state — изолируй fixtures
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        День 154 (Вс): Deploy, портфолио и финальное ревью

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью
                                                                                                                                                                                                                        \nВремя (лайт): ~50м теория · ~1.5ч практика (MVP) · ~10м Git
                                                                                                                                                                                                                        \nСвязь с проектом: шаг к DevHub Capstone

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Теория

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Финальный день — deploy, портфолио и рефлексия. Frontend → Vercel/Netlify (root frontend/, VITE_API_URL = production API). Backend + managed PostgreSQL → Render/Railway/Neon. После deploy: обнови CORS для Vercel domain, rotate JWT_SECRET если был в git, env vars в cloud dashboard.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Live HTTPS demo — критерий сдачи: register → login → CRUD в браузере. FINAL_REVIEW.md: что узнал за 22 недели, что бы сделал иначе. GitHub Profile README — таблица всех 22 проектов со ссылками. README DevHub: badges, demo URL, screenshots, docker setup, architecture.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Free tier cold start 30–60 сек — документируй. Забытый CORS update — API works in curl, fails в browser на Vercel. 2-минутный pitch DevHub — устная репетиция архитектуры. Тег week-22-done — финиш роадмапа. Поздравляем: ты junior full-stack ready.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ментальная модель: деплой — это момент, когда проект перестаёт быть «у меня на компьютере» и становится реальным продуктом, доступным по HTTPS кому угодно в интернете — переход от localhost к публичному URL меняет требования к конфигурации (CORS, секреты, переменные окружения) даже если код не изменился ни на строчку. Для junior-кандидата live demo — это разница между «я утверждаю, что умею» и «вот ссылка, попробуйте сами»: ссылку на живой проект рекрутер откроет с гораздо большей вероятностью, чем будет разбираться, как поднять твой репозиторий локально.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Конкретный пример типичного провала: backend работает и отвечает на curl-запросы с production URL, но при заходе через браузер запросы падают с CORS error — потому что при деплое забыли добавить домен Vercel в whitelist Access-Control-Allow-Origin, который до этого содержал только localhost:5173. Частое заблуждение — «раз всё запушено и задеплоено, работа закончена» — но FINAL_REVIEW.md и обновлённый GitHub Profile README — не бюрократия, а то, что реально увидит рекрутер или технический интервьюер в первую очередь: рефлексия о пройденном пути показывает зрелость мышления не хуже самого кода. Тег week-22-done, который ты ставишь сегодня, закрывает 22-недельный путь — но именно эта финальная неделя, с её деплоем, документацией и портфолио, превращает набор учебных проектов в осязаемое доказательство готовности к первой работе full-stack разработчиком.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Читать:

                                                                                                                                                                                                                        \n\n

                                                                                                                                                                                                                        Ключевая мысль: deploy + FINAL_REVIEW + profile README — три грани финиша capstone.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (полный трек)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Deploy backend: Render/Railway — connect repo, DATABASE_URL + JWT_SECRET
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Deploy DB: managed PostgreSQL, run migrations + seed
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Deploy frontend: Vercel — root frontend/, VITE_API_URL = production API URL
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Update CORS — добавь Vercel domain
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь live demo: HTTPS, register → login → CRUD
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        11. README: badges, live demo URLs, screenshots/GIF, tech stack
                                                                                                                                                                                                                        12. \n
                                                                                                                                                                                                                        13. FINAL_REVIEW.md: что узнал, что бы сделал иначе
                                                                                                                                                                                                                        14. \n
                                                                                                                                                                                                                        15. GitHub Profile README: таблица 22 проектов (как в projects.md)
                                                                                                                                                                                                                        16. \n
                                                                                                                                                                                                                        17. Резюме PDF с live links; 2-мин pitch DevHub
                                                                                                                                                                                                                        18. \n
                                                                                                                                                                                                                        19. Пройди ревью-чеклист — ≥ 80% уверенных ответов
                                                                                                                                                                                                                        20. \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии:\n- [ ] Live HTTPS demo (frontend + API)\n- [ ] FINAL_REVIEW.md заполнен\n- [ ] GitHub profile README обновлён со ссылками на все 22 проекта\n- [ ] README DevHub — demo link, docker setup, architecture, tests

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Практика (лайт / MVP)

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        1. Deploy backend: Render/Railway — connect repo, DATABASE_URL + JWT_SECRET
                                                                                                                                                                                                                        2. \n
                                                                                                                                                                                                                        3. Deploy DB: managed PostgreSQL, run migrations + seed
                                                                                                                                                                                                                        4. \n
                                                                                                                                                                                                                        5. Deploy frontend: Vercel — root frontend/, VITE_API_URL = production API URL
                                                                                                                                                                                                                        6. \n
                                                                                                                                                                                                                        7. Update CORS — добавь Vercel domain
                                                                                                                                                                                                                        8. \n
                                                                                                                                                                                                                        9. Проверь live demo: HTTPS, register → login → CRUD
                                                                                                                                                                                                                        10. \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Если застрял

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Застрял >20 мин — выпиши вход/выход задачи в 3 строки. Сделай минимальный пример в playground.*, без копипаста из ИИ.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Git

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Закоммить изменения дня: git add week-22-capstone/git commit -m \"week 22 day 154: DevHub deploy portfolio FINAL_REVIEW\"
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Поставь тег: git tag week-22-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Push tags: git push origin main --tags
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ловушки

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Забытый CORS update — API works in curl, fails in browser on Vercel
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Free tier cold start 30–60 сек — документируй в README
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проект недели

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        DevHub Capstone — финальный проект роадмапа

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Полная спецификация: docs/projects.md — Неделя 22, DevHub Capstone

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Концепция

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Персональная платформа разработчика: дашборд + заметки + задачи + интеграция с GitHub API (или виджет погоды) — production full-stack app.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Обязательный стек

                                                                                                                                                                                                                        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                                                                                                                                                                        СлойТехнологии
                                                                                                                                                                                                                        FrontendReact 18+, TypeScript, React Router, Context/Zustand
                                                                                                                                                                                                                        BackendFastAPI или Express (один основной)
                                                                                                                                                                                                                        БДPostgreSQL, миграции, seed
                                                                                                                                                                                                                        AuthJWT (register/login), protected routes
                                                                                                                                                                                                                        InfraDocker Compose локально, CI (GitHub Actions)
                                                                                                                                                                                                                        DeployFrontend → Vercel/Netlify, Backend + DB → Render/Railway/Neon
                                                                                                                                                                                                                        Qualitypytest ≥ 15, Vitest ≥ 12, ESLint, README, .env.example
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Функции MVP

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        См. projects.md: Auth, Tasks, Notes, Dashboard, Profile, API, Security, Tests, Docs.

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Структура репозитория

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        week-22-capstone/\n├── frontend/\n├── backend/\n├── docker-compose.yml\n├── .github/workflows/ci.yml\n├── SECURITY.md\n├── ARCHITECTURE.md\n├── FINAL_REVIEW.md\n└── README.md\n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Критерии сдачи

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • Live HTTPS demo (frontend + API)
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • docker compose up поднимает всё локально
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Auth end-to-end работает
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • ≥ 5 сущностей в БД со связями
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • CI green on push
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • FINAL_REVIEW.md заполнен
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • GitHub profile README — ссылки на все 22 проекта
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Тег week-22-done
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Связь с проектами 13–21

                                                                                                                                                                                                                        \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
                                                                                                                                                                                                                        НеделяПереиспользуешь
                                                                                                                                                                                                                        14 — DashboardUI виджеты, fetch
                                                                                                                                                                                                                        18/19 — APICRUD, Swagger
                                                                                                                                                                                                                        20 — Secure NotesJWT, тесты
                                                                                                                                                                                                                        21 — Dockercompose, monorepo
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Nice-to-have: projects.md.

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Ревью-чеклист

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                          \n
                                                                                                                                                                                                                        • HTML/CSS: block vs inline, Flexbox vs Grid?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • JS: замыкание, Event Loop, var/let/const?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • React: key, useState vs useEffect?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Python: Big O, магические методы, venv?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • SQL: JOIN, индексы, injection?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Node: middleware, connection pool?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • Full-Stack: REST, CORS, JWT, Docker?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        • DevHub: архитектура за 2 минуты?
                                                                                                                                                                                                                        • \n
                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        80%+ уверенных ответов — ты готов к junior full-stack. Поздравляем с завершением 22-недельного роадмапа!

                                                                                                                                                                                                                        \n

                                                                                                                                                                                                                        Проверь себя

                                                                                                                                                                                                                        \n
                                                                                                                                                                                                                        \nЧто должно получиться к концу недели?\n\nРаботающий проект **DevHub Capstone** в `learning-log/week-22/`, осмысленная Git-история, тег `week-22-done`.\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nГлавный навык недели одной фразой?\n\nProduction capstone: DevHub full-stack\n\n
                                                                                                                                                                                                                        \n\n
                                                                                                                                                                                                                        \nМожно ли пропустить день?\n\nНет — дни связаны. В **лайт-режиме** сократи практику до MVP, но теорию и Git-коммит не пропускай.\n\n
                                                                                                                                                                                                                        ", "toc": [{"id": "week-22-day-148", "label": "День 148 (Пн): Планирование DevHub Capstone"}, {"id": "week-22-day-149", "label": "День 149 (Вт): Backend DevHub"}, {"id": "week-22-day-150", "label": "День 150 (Ср): Frontend DevHub (React + TypeScript)"}, {"id": "week-22-day-151", "label": "День 151 (Чт): Auth — JWT end-to-end"}, {"id": "week-22-day-152", "label": "День 152 (Пт): Docker — локальный full-stack"}, {"id": "week-22-day-153", "label": "День 153 (Сб): Тесты и CI"}, {"id": "week-22-day-154", "label": "День 154 (Вс): Deploy, портфолио и финальное ревью"}, {"id": "week-22-project", "label": "Проект недели"}, {"id": "week-22-ревью-чеклист", "label": "Ревью-чеклист"}, {"id": "week-22-review", "label": "Проверь себя"}], "text": "Неделя 22: DevHub Capstone — финальный full-stack проект Цель недели: собрать, протестировать и задеплоить DevHub — единый capstone, объединяющий весь стек 22 недель обучения. Литература: docs/projects.md — DevHub Capstone , Vercel Docs , Render Docs , GitHub Actions Проект недели: DevHub Capstone — персональная платформа разработчика: дашборд + заметки + задачи + GitHub API. Git: папка learning-log/week-22-capstone/ , feature-ветки по дням 149–153; тег week-22-done + обновление GitHub Profile README. Не начинайте с нуля в последний день. Планируйте в день 148, кодите 149–153, деплой и портфолио — в день 154. Полная спецификация MVP, стека и критериев сдачи — в каталоге проектов . День 148 (Пн): Планирование DevHub Capstone Время (полный): ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревь…"} \ No newline at end of file diff --git a/roadmap/weeks/week-00.md b/roadmap/weeks/week-00.md index 7e7e00e..e99cc3b 100644 --- a/roadmap/weeks/week-00.md +++ b/roadmap/weeks/week-00.md @@ -19,11 +19,17 @@ ### Теория -Веб-разработка начинается не с кода, а со **среды**: редактор, браузер с DevTools, терминал, Git. Эти инструменты останутся с вами на годы. +Веб-разработка начинается не с кода, а со **среды**: редактор, браузер с DevTools, терминал, Git. Эти инструменты останутся с вами на годы, поэтому час, потраченный сегодня на настройку, окупится десятки раз позже. -**VS Code** — редактор с встроенным терминалом и Git. **Chrome DevTools** — Elements (DOM/CSS), Console (ошибки JS), Network (запросы). **Git** — история изменений; без него нет портфолио. +Удобная мысленная модель: редактор — мастерская, где вы создаёте вещь; браузер с DevTools — рентген, который показывает, что получилось на самом деле; терминал — пульт, откуда команды отдаются инструментам напрямую, а не кликами мыши; Git — машина времени, которая помнит каждую версию вашей работы. -**Ключевая мысль:** стабильная среда важнее скорости «сразу писать код». +**VS Code** — редактор с встроенным терминалом и подсветкой Git-изменений прямо в файлах. **Chrome DevTools** — три вкладки на каждый день: Elements показывает живое дерево DOM и применённые CSS-правила, Console выводит ошибки JavaScript, Network — что загрузила страница и сколько это заняло. **Git** — история изменений; без него нет портфолио и нет пути назад, если что-то сломалось. + +Пример: через несколько недель вы случайно удалите важный кусок CSS и не заметите это сразу — `git diff` покажет ровно те строки, что изменились со вчерашнего коммита, и восстановить код можно за секунды вместо часа гаданий. + +Частая ошибка новичков — писать код без Git «чтобы не тратить время на настройку», откладывая репозиторий «на потом, когда будет что показать». Тогда первые недели прогресса нигде не задокументированы. Такая же ошибка — отлаживать вёрстку методом «поменял файл — обновил страницу — посмотрел», хотя Elements с редактированием стилей на лету делает это быстрее. + +**Ключевая мысль:** стабильная среда важнее скорости «сразу писать код» — сегодняшняя практика единственный раз в маршруте посвящена только настройке, чтобы дальше ничего не отвлекало от обучения. **Читать:** [Как начать](../../docs/getting-started.md) — таблица инструментов. @@ -56,11 +62,17 @@ ### Теория -Публичный `learning-log` — портфолио **в процессе**. Рекрутер видит дисциплину: коммиты, сообщения, рост по неделям — не только финальный zip. +Публичный `learning-log` — портфолио **в процессе**, а не готовая витрина. Рекрутер, который откроет ваш GitHub через полгода, видит не только финальный код, но и дисциплину: регулярные коммиты, внятные сообщения, заметный рост качества от недели 1 к неделе 20. Это рассказывает историю лучше, чем строчка в резюме. + +Мысленная модель: репозиторий — дневник разработчика, а не архив готовых работ. Каждый коммит — запись «что сделано и зачем», а вместе они складываются в график активности на странице профиля GitHub. Пустые недели в этом графике так же красноречивы, как и активные. -Репозиторий создаёте **под своим аккаунтом**, пустой (без README от GitHub), затем клонируете себе. Не клонируйте чужой learning-log — это должен быть ваш граф коммитов. +Репозиторий создаёте **под своим аккаунтом**, пустым (без README, лицензии и `.gitignore` от GitHub — их вы добавите сами локально, чтобы первый коммит был осмысленным, а не автосгенерированным), затем клонируете себе на компьютер. Важно не путать: клонировать нужно **свой** пустой репозиторий, а не чужой существующий `learning-log` — иначе история коммитов будет принадлежать другому человеку, и смысл портфолио теряется. -**Ключевая мысль:** репозиторий появляется до первой строки HTML. +Почему это важно для всего маршрута: начиная с недели 1 каждый день заканчивается коммитом в эту же папку. Если репозиторий настроен неправильно сегодня — с чужой историей или без `.gitignore` — проблему придётся решать посреди недели 1, отвлекаясь от HTML. + +Частое заблуждение — думать, что показывать портфолио стоит только после «идеального» результата, поэтому можно закоммитить всё одним большим коммитом в конце. На деле частые маленькие коммиты с понятными сообщениями (`feat: add contact form`, а не `fix`) сами по себе сигнал профессионализма — и заметны раньше, чем содержимое кода. + +**Ключевая мысль:** репозиторий появляется до первой строки HTML — сегодняшняя практика это подтверждает: вы создаёте `learning-log`, `.gitignore` и `README.md` ещё до того, как напишете хоть один тег. ### Практика (полный трек) 1. Аккаунт GitHub (если нет) + 2FA по возможности @@ -104,7 +116,9 @@ git push -u origin main ### Теория -Каждый учебный день недель 1–22: +Прежде чем нырять в HTML на неделе 1, полезно понять устройство самого маршрута — это экономит время в первый рабочий день. Мысленная модель: маршрут — 22 «спринта» по неделе, а не линейный курс видео. Каждая неделя даёт один законченный проект, и пропущенный день ломает не столько расписание, сколько внутреннюю логику: практика четверга опирается на код, написанный в понедельник. + +Каждый учебный день недель 1–22 устроен одинаково: | Блок | Зачем | |------|--------| @@ -114,9 +128,11 @@ git push -u origin main | **Git** | Минимум один осмысленный коммит | | **Если застрял** | Подсказка по теме дня, не копипаст | -**Полный трек** (~5–7 ч/день): максимум глубины. **Лайт** (~3–4 ч): теория + лайт-практика + Git; проект недели — в урезанном DoD из каталога. +**Полный трек** (~5–7 ч/день): максимум глубины, все пункты практики, углублённое ревью. **Лайт** (~3–4 ч): теория читается полностью, практика — только MVP-подмножество, коммит обязателен; проект недели сдаётся в урезанном DoD (Definition of Done) из каталога проектов — согласованный меньший набор требований, а не «сделаю потом». + +Почему это важно для следующих недель: если сегодня не разобраться, чем полный трек отличается от лайт, велик риск на неделе 5 обнаружить накопившееся отставание, которое сложно объяснить — просто не был понятен ожидаемый объём практики. Пример: студент на лайт-треке, который в день 3 недели 1 делает только MVP-пункты вместо всех пунктов «полного трека», не отстаёт — он следует своему треку, если проект недели в итоге собран по лайт-DoD. -Протокол «анти-вайбкодер»: ИИ объясняет концепцию или ревьюит **ваш** код. Не пишет за вас. +Протокол «анти-вайбкодер» — отдельное важное правило: ИИ-ассистент в этом маршруте объясняет концепцию или ревьюит **уже написанный вами** код, но не пишет решение за вас. Частая ошибка новичков — попросить ИИ «сделай форму валидации» и скопировать ответ: код появится, а навык — нет, и это станет заметно на итоговом проекте. Сегодняшняя практика — прочитать introduction и каталог проектов, чтобы осознанно выбрать трек, а не выяснять правила на ходу в понедельник. **Читать:** - [Введение](../introduction.md) diff --git a/roadmap/weeks/week-01.md b/roadmap/weeks/week-01.md index 1999f24..8176a88 100644 --- a/roadmap/weeks/week-01.md +++ b/roadmap/weeks/week-01.md @@ -20,8 +20,8 @@ ## День 0 (до понедельника): Git и GitHub — подготовка -> **Время (полный):** ~35м теория · ~1.5ч практика · ~10м Git · ~15м ревью -> **Время (лайт):** ~15м теория · ~40м практика (MVP) · ~10м Git +> **Время (полный):** ~55м теория · ~1.5ч практика · ~10м Git · ~15м ревью +> **Время (лайт):** ~25м теория · ~40м практика (MVP) · ~10м Git > **Связь с проектом:** шаг к **Portfolio Landing** > Если Git уже установлен и аккаунт GitHub есть — пройди чеклист и переходи к дню 1. @@ -34,7 +34,13 @@ GitHub — это удалённое зеркало репозитория плюс социальная платформа. Публичный `learning-log` с осмысленной историей коммитов — живое портфолио: рекрутер видит не только код, но и то, как ты думаешь и работаешь. -**Ключевая мысль:** коммит — это именованный снимок проекта, а не просто «сохранить файл». +Почему это критично для всех следующих 22 недель: каждый день маршрута заканчивается коммитом, и от того, насколько уверенно ты сегодня освоишь `add` → `commit` → `push`, зависит, будет ли Git помогать или пугать всю дорогу. На неделе 6 появятся ветки для фич, дальше — пул-реквесты и код-ревью; без твёрдой базы трёх зон эти темы превращаются в магию вместо инструмента. + +Конкретный пример рабочего цикла: правишь `index.html`, `git status` показывает файл как изменённый (working directory), `git add index.html` переносит его в staging, `git commit -m "..."` создаёт снимок в истории, `git push` отправляет его на GitHub — до этого момента изменения видны только тебе локально. + +Частое заблуждение новичков — считать, что `git add` уже «сохраняет» изменения, и после него можно закрыть терминал. На деле без `git commit` изменения остаются в staging и никуда не «доезжают»; а без `git push` коммит остаётся только на твоём компьютере и не появится на GitHub, даже если локально `git log` показывает его. + +**Ключевая мысль:** коммит — это именованный снимок проекта, а не просто «сохранить файл»; сегодняшняя практика — прогнать этот цикл от установки Git до первого `git push` вручную, чтобы завтра, в день 1, писать `index.html` и коммитить его уже не задумываясь о механике. **Читать:** - [Pro Git: Введение](https://git-scm.com/book/en/v2/Getting-Started-About-Version-Control) — зачем VCS: история, откат, ветки @@ -71,6 +77,7 @@ GitHub — это удалённое зеркало репозитория пл - [ ] `.gitignore` закоммичен + ### Если застрял Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному. @@ -87,8 +94,8 @@ GitHub — это удалённое зеркало репозитория пл ## День 1 (Mon): Структура документа, первый index.html, первый коммит страницы -> **Время (полный):** ~1.5ч теория · ~3.5ч практика · ~15м Git · ~45м ревью -> **Время (лайт):** ~35м теория · ~1.5ч практика (MVP) · ~10м Git +> **Время (полный):** ~2ч теория · ~3.5ч практика · ~15м Git · ~45м ревью +> **Время (лайт):** ~55м теория · ~1.5ч практика (MVP) · ~10м Git > **Связь с проектом:** шаг к **Portfolio Landing** ### Теория @@ -101,7 +108,13 @@ HTML — это не язык оформления, а язык **смысла** Атрибуты дополняют теги: `id` — уникальный якорь (один на страницу), `class` — группа для стилей, `href` и `src` — адреса ссылок и ресурсов. У `img` атрибут `alt` обязателен, если картинка несёт смысл — иначе скринридер и поисковик не поймут, что на изображении. -**Ключевая мысль:** HTML описывает структуру и смысл; браузер из неё строит DOM-дерево. +Мысленная модель, которая пригодится на всех следующих неделях: HTML — это скелет, CSS (неделя 2) — одежда и внешний вид, JavaScript (неделя 4+) — мышцы и поведение. Скелет должен быть правильным сам по себе, ещё до того, как на него что-то надето: скринридер и поисковик читают именно разметку, а не то, как страница выглядит визуально после стилизации. + +Конкретный пример: если сверстать блок «Обо мне» через `
                                                                                                                                                                                                                        Обо мне
                                                                                                                                                                                                                        Текст...
                                                                                                                                                                                                                        `, страница может выглядеть нормально после CSS, но программа чтения с экрана объявит просто «группа, группа» — пользователь не поймёт, что перед ним заголовок раздела. Замена на `

                                                                                                                                                                                                                        Обо мне

                                                                                                                                                                                                                        Текст...

                                                                                                                                                                                                                        ` решает проблему без единой строчки CSS. + +Частое заблуждение новичков — писать `
                                                                                                                                                                                                                        ` и `` для всего подряд «а потом стилями сделаю красиво», откладывая выбор семантики на потом. На деле семантика закладывается сразу: разметка описывает смысл контента независимо от того, как он будет оформлен, и переписывать структуру после того, как всё завязано на классы, дороже, чем сделать правильно с первого раза. Сегодняшняя практика — первый `index.html` — это и есть тренировка такого выбора: заголовки по иерархии, `nav` для навигации, осмысленный `alt` у изображения. + +**Ключевая мысль:** HTML описывает структуру и смысл; браузер из неё строит DOM-дерево, а CSS и JS лишь надстраиваются сверху. **Читать:** - [MDN: Введение в HTML](https://developer.mozilla.org/ru/docs/Learn/HTML/Introduction_to_HTML) — разметка описывает смысл, браузер строит DOM-дерево @@ -130,9 +143,10 @@ HTML — это не язык оформления, а язык **смысла** > Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит. + ### Если застрял -UI «не работает» — проверь селекторы в Elements, слушатели в Event Listeners, сеть во вкладке Network. +Не понимаешь ошибку — прочитай её с конца: файл, строка, тип. Открой DevTools / терминал и воспроизведи на 5 строках кода. ### Git ```bash @@ -153,8 +167,8 @@ git push ## День 2 (Tue): Семантическая разметка -> **Время (полный):** ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью -> **Время (лайт):** ~30м теория · ~1ч практика (MVP) · ~10м Git +> **Время (полный):** ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью +> **Время (лайт):** ~55м теория · ~1ч практика (MVP) · ~10м Git > **Связь с проектом:** шаг к **Portfolio Landing** ### Теория @@ -165,6 +179,14 @@ git push `section` группирует тематически связанный контент с заголовком (блок «О себе», «Навыки»). `article` — самодостаточная единица: пост в блоге, карточка товара, новость — то, что можно вынести в RSS отдельно. `aside` — боковое дополнение к основному потоку: виджет «сейчас изучаю», реклама, сноски. Пара `figure` + `figcaption` связывает иллюстрацию с подписью; элемент `time` с атрибутом `datetime` даёт машиночитаемую дату для календарей и микроразметки. +Мысленная модель: представь страницу как здание с указателями. `header` — вывеска у входа, `nav` — карта этажей у лифта, `main` — сам этаж с содержимым, `aside` — информационный стенд в коридоре, `footer` — табличка на выходе. Указатели помогают ориентироваться даже тому, кто не видит всё здание целиком — например, идёт по нему на ощупь, как скринридер идёт по DOM. + +Почему это важно дальше: на неделе 6 ты добавишь JavaScript, который будет искать элементы по структуре страницы (`document.querySelector('main')`, обработчики на `nav a`), а на неделях с React — компоненты будут возвращать именно такую семантическую разметку. Если сегодня привыкнуть мыслить landmark-ами, а не «div с классом wrapper», работа с фреймворками пойдёт быстрее. + +Пример: `
                                                                                                                                                                                                                        Заголовок
                                                                                                                                                                                                                        ` технически работает, но `

                                                                                                                                                                                                                        Заголовок

                                                                                                                                                                                                                        ` даёт браузеру и поисковику готовую структуру поста без единой строчки JS. + +Частое заблуждение — использовать `section` для любого визуального блока с отступом. `section` уместен только когда у контента есть собственный заголовок и он тематически целостен; блок для чисто визуального разделения (например, обёртка для центрирования) так и остаётся `div`. Сегодня в практике ты рефакторишь вчерашний `index.html` именно с этим фильтром: «у этого блока есть заголовок и смысл, или это просто обёртка для стилей?» + **Ключевая мысль:** правильный тег — это документация для людей и машин; `div` — последний выбор, не первый. **Читать:** @@ -190,9 +212,10 @@ git push > Лайт-DoD: этих шагов достаточно, если теория прочитана и есть коммит. + ### Если застрял -Запутался в структуре файлов — нарисуй дерево папок на бумаге, потом создай пустые файлы и заполни по одному. +Устал — сделай коммит текущего прогресса с честным сообщением `wip:` и паузу 10 минут. Не геройствуй. ### Git ```bash @@ -206,8 +229,8 @@ git push ## День 3 (Wed): Ссылки, изображения, медиа -> **Время (полный):** ~1ч теория · ~2.5ч практика · ~15м Git · ~45м ревью -> **Время (лайт):** ~30м теория · ~1ч практика (MVP) · ~10м Git +> **Время (полный):** ~2ч теория · ~2.5ч практика · ~15м Git · ~45м ревью +> **Время (лайт):** ~55м теория · ~1ч практика (MVP) · ~10м Git > **Связь с проектом:** шаг к **Portfolio Landing** ### Теория @@ -218,7 +241,15 @@ git push Видео встраивается тегом `